linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] perf: cs-etm: Print auxtrace info even if OpenCSD isn't linked
@ 2022-12-12 15:55 James Clark
  2022-12-12 15:55 ` [PATCH 1/5] perf: cs-etm: Print unknown header version as an error James Clark
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: James Clark @ 2022-12-12 15:55 UTC (permalink / raw)
  To: linux-perf-users
  Cc: Al.Grant, James Clark, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Mark Rutland, Alexander Shishkin,
	Jiri Olsa, Namhyung Kim, John Garry, Will Deacon, Mike Leach,
	Leo Yan, Mathieu Poirier, Suzuki K Poulose, linux-kernel,
	linux-arm-kernel, coresight

The auxtrace info header can be useful for debugging, and at the
moment it's possible to record a file without OpenCSD linked but
not view the header even though it should be possible to do.

This patchset tidies up some of the related functions and
improves some of the error messages before making the above
possible in the last commit.

Testing done:

 * Compiled on x86 and Arm both with and without CORESIGHT=1
 * Ran the Coresight tests

Applies to perf/core (0c3852adae8)

James Clark (5):
  perf: cs-etm: Print unknown header version as an error
  perf: cs-etm: Remove unused stub methods
  perf: cs-etm: Tidy up auxtrace info header printing
  perf: cs-etm: Cleanup cs_etm__process_auxtrace_info()
  perf: cs-etm: Print auxtrace info even if OpenCSD isn't linked

 tools/perf/util/Build         |   1 +
 tools/perf/util/cs-etm-base.c | 174 ++++++++++++++++++++++++++++
 tools/perf/util/cs-etm.c      | 208 +++-------------------------------
 tools/perf/util/cs-etm.h      |  46 ++------
 4 files changed, 200 insertions(+), 229 deletions(-)
 create mode 100644 tools/perf/util/cs-etm-base.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/5] perf: cs-etm: Print unknown header version as an error
  2022-12-12 15:55 [PATCH 0/5] perf: cs-etm: Print auxtrace info even if OpenCSD isn't linked James Clark
@ 2022-12-12 15:55 ` James Clark
  2022-12-12 15:55 ` [PATCH 2/5] perf: cs-etm: Remove unused stub methods James Clark
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: James Clark @ 2022-12-12 15:55 UTC (permalink / raw)
  To: linux-perf-users
  Cc: Al.Grant, James Clark, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Mark Rutland, Alexander Shishkin,
	Jiri Olsa, Namhyung Kim, John Garry, Will Deacon, Mike Leach,
	Leo Yan, Mathieu Poirier, Suzuki K Poulose, linux-kernel,
	linux-arm-kernel, coresight

This is an error rather than just for the raw trace dump so always print
it as an error. Also remove the duplicate header version check.

Signed-off-by: James Clark <james.clark@arm.com>
---
 tools/perf/util/cs-etm.c | 12 ++----------
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 16db965ac995..aeb1e30888db 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -2623,14 +2623,7 @@ static void cs_etm__print_auxtrace_info(__u64 *val, int num)
 {
 	int i, cpu = 0, version, err;
 
-	/* bail out early on bad header version */
 	version = val[0];
-	if (version > CS_HEADER_CURRENT_VERSION) {
-		/* failure.. return */
-		fprintf(stdout, "	Unknown Header Version = %x, ", version);
-		fprintf(stdout, "Version supported <= %x\n", CS_HEADER_CURRENT_VERSION);
-		return;
-	}
 
 	for (i = 0; i < CS_HEADER_VERSION_MAX; i++)
 		fprintf(stdout, cs_etm_global_header_fmts[i], val[i]);
@@ -2916,9 +2909,8 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
 	/* Look for version of the header */
 	hdr_version = ptr[0];
 	if (hdr_version > CS_HEADER_CURRENT_VERSION) {
-		/* print routine will print an error on bad version */
-		if (dump_trace)
-			cs_etm__print_auxtrace_info(auxtrace_info->priv, 0);
+		pr_err("\nCS ETM Trace: Unknown Header Version = %#" PRIx64, hdr_version);
+		pr_err(", version supported <= %x\n", CS_HEADER_CURRENT_VERSION);
 		return -EINVAL;
 	}
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/5] perf: cs-etm: Remove unused stub methods
  2022-12-12 15:55 [PATCH 0/5] perf: cs-etm: Print auxtrace info even if OpenCSD isn't linked James Clark
  2022-12-12 15:55 ` [PATCH 1/5] perf: cs-etm: Print unknown header version as an error James Clark
@ 2022-12-12 15:55 ` James Clark
  2022-12-12 15:55 ` [PATCH 3/5] perf: cs-etm: Tidy up auxtrace info header printing James Clark
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: James Clark @ 2022-12-12 15:55 UTC (permalink / raw)
  To: linux-perf-users
  Cc: Al.Grant, James Clark, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Mark Rutland, Alexander Shishkin,
	Jiri Olsa, Namhyung Kim, John Garry, Will Deacon, Mike Leach,
	Leo Yan, Mathieu Poirier, Suzuki K Poulose, linux-kernel,
	linux-arm-kernel, coresight

These aren't used outside of cs-etm so don't need stubs. Leave
cs_etm__process_auxtrace_info() which is used externally, and add an
error message so that it's obvious to users why it causes errors.

Signed-off-by: James Clark <james.clark@arm.com>
---
 tools/perf/util/cs-etm.h | 34 ++--------------------------------
 1 file changed, 2 insertions(+), 32 deletions(-)

diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h
index 90c83f932d9a..401f74be98d6 100644
--- a/tools/perf/util/cs-etm.h
+++ b/tools/perf/util/cs-etm.h
@@ -7,6 +7,7 @@
 #ifndef INCLUDE__UTIL_PERF_CS_ETM_H__
 #define INCLUDE__UTIL_PERF_CS_ETM_H__
 
+#include "debug.h"
 #include "util/event.h"
 #include <linux/bits.h>
 
@@ -218,40 +219,9 @@ static inline int
 cs_etm__process_auxtrace_info(union perf_event *event __maybe_unused,
 			      struct perf_session *session __maybe_unused)
 {
+	pr_err("\nCS ETM Trace: OpenCSD is not linked in, please recompile with CORESIGHT=1\n");
 	return -1;
 }
-
-static inline int cs_etm__get_cpu(u8 trace_chan_id __maybe_unused,
-				  int *cpu __maybe_unused)
-{
-	return -1;
-}
-
-static inline int cs_etm__etmq_set_tid(
-				struct cs_etm_queue *etmq __maybe_unused,
-				pid_t tid __maybe_unused,
-				u8 trace_chan_id __maybe_unused)
-{
-	return -1;
-}
-
-static inline bool cs_etm__etmq_is_timeless(
-				struct cs_etm_queue *etmq __maybe_unused)
-{
-	/* What else to return? */
-	return true;
-}
-
-static inline void cs_etm__etmq_set_traceid_queue_timestamp(
-				struct cs_etm_queue *etmq __maybe_unused,
-				u8 trace_chan_id __maybe_unused) {}
-
-static inline struct cs_etm_packet_queue *cs_etm__etmq_get_packet_queue(
-				struct cs_etm_queue *etmq __maybe_unused,
-				u8 trace_chan_id __maybe_unused)
-{
-	return NULL;
-}
 #endif
 
 #endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/5] perf: cs-etm: Tidy up auxtrace info header printing
  2022-12-12 15:55 [PATCH 0/5] perf: cs-etm: Print auxtrace info even if OpenCSD isn't linked James Clark
  2022-12-12 15:55 ` [PATCH 1/5] perf: cs-etm: Print unknown header version as an error James Clark
  2022-12-12 15:55 ` [PATCH 2/5] perf: cs-etm: Remove unused stub methods James Clark
@ 2022-12-12 15:55 ` James Clark
  2022-12-12 15:55 ` [PATCH 4/5] perf: cs-etm: Cleanup cs_etm__process_auxtrace_info() James Clark
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: James Clark @ 2022-12-12 15:55 UTC (permalink / raw)
  To: linux-perf-users
  Cc: Al.Grant, James Clark, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Mark Rutland, Alexander Shishkin,
	Jiri Olsa, Namhyung Kim, John Garry, Will Deacon, Mike Leach,
	Leo Yan, Mathieu Poirier, Suzuki K Poulose, linux-kernel,
	linux-arm-kernel, coresight

cs_etm__print_auxtrace_info() is called twice in case there is an error
somewhere in cs_etm__process_auxtrace_info(), but all the info is
already available at the beginning so just print it there instead.

Also use u64 and the already cast ptr variable to make it more
consistent with the rest of the etm code.

Signed-off-by: James Clark <james.clark@arm.com>
---
 tools/perf/util/cs-etm.c | 28 ++++++++++------------------
 1 file changed, 10 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index aeb1e30888db..bf8fbcec2d69 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -2541,14 +2541,14 @@ static const char * const cs_etmv4_priv_fmts[] = {
 };
 
 static const char * const param_unk_fmt =
-	"	Unknown parameter [%d]	       %llx\n";
+	"	Unknown parameter [%d]	       %"PRIx64"\n";
 static const char * const magic_unk_fmt =
-	"	Magic number Unknown	       %llx\n";
+	"	Magic number Unknown	       %"PRIx64"\n";
 
-static int cs_etm__print_cpu_metadata_v0(__u64 *val, int *offset)
+static int cs_etm__print_cpu_metadata_v0(u64 *val, int *offset)
 {
 	int i = *offset, j, nr_params = 0, fmt_offset;
-	__u64 magic;
+	u64 magic;
 
 	/* check magic value */
 	magic = val[i + CS_ETM_MAGIC];
@@ -2580,10 +2580,10 @@ static int cs_etm__print_cpu_metadata_v0(__u64 *val, int *offset)
 	return 0;
 }
 
-static int cs_etm__print_cpu_metadata_v1(__u64 *val, int *offset)
+static int cs_etm__print_cpu_metadata_v1(u64 *val, int *offset)
 {
 	int i = *offset, j, total_params = 0;
-	__u64 magic;
+	u64 magic;
 
 	magic = val[i + CS_ETM_MAGIC];
 	/* total params to print is NR_PARAMS + common block size for v1 */
@@ -2619,7 +2619,7 @@ static int cs_etm__print_cpu_metadata_v1(__u64 *val, int *offset)
 	return 0;
 }
 
-static void cs_etm__print_auxtrace_info(__u64 *val, int num)
+static void cs_etm__print_auxtrace_info(u64 *val, int num)
 {
 	int i, cpu = 0, version, err;
 
@@ -2925,6 +2925,9 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
 	pmu_type = (unsigned int) ((hdr[CS_PMU_TYPE_CPUS] >> 32) &
 				    0xffffffff);
 
+	if (dump_trace)
+		cs_etm__print_auxtrace_info(ptr, num_cpu);
+
 	/*
 	 * Create an RB tree for traceID-metadata tuple.  Since the conversion
 	 * has to be made for each packet that gets decoded, optimizing access
@@ -3074,10 +3077,6 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
 		goto err_delete_thread;
 	}
 
-	if (dump_trace) {
-		cs_etm__print_auxtrace_info(auxtrace_info->priv, num_cpu);
-	}
-
 	err = cs_etm__synth_events(etm, session);
 	if (err)
 		goto err_delete_thread;
@@ -3113,12 +3112,5 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
 	intlist__delete(traceid_list);
 err_free_hdr:
 	zfree(&hdr);
-	/*
-	 * At this point, as a minimum we have valid header. Dump the rest of
-	 * the info section - the print routines will error out on structural
-	 * issues.
-	 */
-	if (dump_trace)
-		cs_etm__print_auxtrace_info(auxtrace_info->priv, num_cpu);
 	return err;
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/5] perf: cs-etm: Cleanup cs_etm__process_auxtrace_info()
  2022-12-12 15:55 [PATCH 0/5] perf: cs-etm: Print auxtrace info even if OpenCSD isn't linked James Clark
                   ` (2 preceding siblings ...)
  2022-12-12 15:55 ` [PATCH 3/5] perf: cs-etm: Tidy up auxtrace info header printing James Clark
@ 2022-12-12 15:55 ` James Clark
  2022-12-12 15:55 ` [PATCH 5/5] perf: cs-etm: Print auxtrace info even if OpenCSD isn't linked James Clark
  2022-12-12 19:50 ` [PATCH 0/5] " Arnaldo Carvalho de Melo
  5 siblings, 0 replies; 7+ messages in thread
From: James Clark @ 2022-12-12 15:55 UTC (permalink / raw)
  To: linux-perf-users
  Cc: Al.Grant, James Clark, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Mark Rutland, Alexander Shishkin,
	Jiri Olsa, Namhyung Kim, John Garry, Will Deacon, Mike Leach,
	Leo Yan, Mathieu Poirier, Suzuki K Poulose, linux-kernel,
	linux-arm-kernel, coresight

hdr is a copy of 3 values of ptr and doesn't need to be long lived. So
just use ptr instead which means the malloc and the extra error path can
be removed to simplify things.

Signed-off-by: James Clark <james.clark@arm.com>
---
 tools/perf/util/cs-etm.c | 26 +++++++++-----------------
 1 file changed, 9 insertions(+), 17 deletions(-)

diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index bf8fbcec2d69..ab30591a6c6a 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -2888,7 +2888,7 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
 	int num_cpu, trcidr_idx;
 	int err = 0;
 	int i, j;
-	u64 *ptr, *hdr = NULL;
+	u64 *ptr = NULL;
 	u64 **metadata = NULL;
 	u64 hdr_version;
 
@@ -2914,15 +2914,8 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
 		return -EINVAL;
 	}
 
-	hdr = zalloc(sizeof(*hdr) * CS_HEADER_VERSION_MAX);
-	if (!hdr)
-		return -ENOMEM;
-
-	/* Extract header information - see cs-etm.h for format */
-	for (i = 0; i < CS_HEADER_VERSION_MAX; i++)
-		hdr[i] = ptr[i];
-	num_cpu = hdr[CS_PMU_TYPE_CPUS] & 0xffffffff;
-	pmu_type = (unsigned int) ((hdr[CS_PMU_TYPE_CPUS] >> 32) &
+	num_cpu = ptr[CS_PMU_TYPE_CPUS] & 0xffffffff;
+	pmu_type = (unsigned int) ((ptr[CS_PMU_TYPE_CPUS] >> 32) &
 				    0xffffffff);
 
 	if (dump_trace)
@@ -2934,10 +2927,8 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
 	 * in anything other than a sequential array is worth doing.
 	 */
 	traceid_list = intlist__new(NULL);
-	if (!traceid_list) {
-		err = -ENOMEM;
-		goto err_free_hdr;
-	}
+	if (!traceid_list)
+		return -ENOMEM;
 
 	metadata = zalloc(sizeof(*metadata) * num_cpu);
 	if (!metadata) {
@@ -2945,6 +2936,9 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
 		goto err_free_traceid_list;
 	}
 
+	/* Start parsing after the common part of the header */
+	i = CS_HEADER_VERSION_MAX;
+
 	/*
 	 * The metadata is stored in the auxtrace_info section and encodes
 	 * the configuration of the ARM embedded trace macrocell which is
@@ -3043,7 +3037,7 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
 
 	etm->num_cpu = num_cpu;
 	etm->pmu_type = pmu_type;
-	etm->snapshot_mode = (hdr[CS_ETM_SNAPSHOT] != 0);
+	etm->snapshot_mode = (ptr[CS_ETM_SNAPSHOT] != 0);
 	etm->metadata = metadata;
 	etm->auxtrace_type = auxtrace_info->type;
 	etm->timeless_decoding = cs_etm__is_timeless_decoding(etm);
@@ -3110,7 +3104,5 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
 	zfree(&metadata);
 err_free_traceid_list:
 	intlist__delete(traceid_list);
-err_free_hdr:
-	zfree(&hdr);
 	return err;
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/5] perf: cs-etm: Print auxtrace info even if OpenCSD isn't linked
  2022-12-12 15:55 [PATCH 0/5] perf: cs-etm: Print auxtrace info even if OpenCSD isn't linked James Clark
                   ` (3 preceding siblings ...)
  2022-12-12 15:55 ` [PATCH 4/5] perf: cs-etm: Cleanup cs_etm__process_auxtrace_info() James Clark
@ 2022-12-12 15:55 ` James Clark
  2022-12-12 19:50 ` [PATCH 0/5] " Arnaldo Carvalho de Melo
  5 siblings, 0 replies; 7+ messages in thread
From: James Clark @ 2022-12-12 15:55 UTC (permalink / raw)
  To: linux-perf-users
  Cc: Al.Grant, James Clark, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Mark Rutland, Alexander Shishkin,
	Jiri Olsa, Namhyung Kim, John Garry, Will Deacon, Mike Leach,
	Leo Yan, Mathieu Poirier, Suzuki K Poulose, linux-kernel,
	linux-arm-kernel, coresight

Printing the info doesn't have any dependency on OpenCSD, and neither
does recording Coresight data. Because it's sometimes useful to look at
the info for debugging, it makes sense to be able to see it on the same
platform that the recording was made on.

So pull the auxtrace info printing parts into a new file that is always
compiled into Perf.

Signed-off-by: James Clark <james.clark@arm.com>
---
 tools/perf/util/Build         |   1 +
 tools/perf/util/cs-etm-base.c | 174 ++++++++++++++++++++++++++++++++++
 tools/perf/util/cs-etm.c      | 170 ++-------------------------------
 tools/perf/util/cs-etm.h      |  12 ++-
 4 files changed, 191 insertions(+), 166 deletions(-)
 create mode 100644 tools/perf/util/cs-etm-base.c

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index ab37f588ee8b..1193b207ef7d 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -125,6 +125,7 @@ ifdef CONFIG_LIBOPENCSD
 perf-$(CONFIG_AUXTRACE) += cs-etm.o
 perf-$(CONFIG_AUXTRACE) += cs-etm-decoder/
 endif
+perf-$(CONFIG_AUXTRACE) += cs-etm-base.o
 
 perf-y += parse-branch-options.o
 perf-y += dump-insn.o
diff --git a/tools/perf/util/cs-etm-base.c b/tools/perf/util/cs-etm-base.c
new file mode 100644
index 000000000000..597542410854
--- /dev/null
+++ b/tools/perf/util/cs-etm-base.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * File for any parts of the Coresight decoding that don't require
+ * OpenCSD.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+
+#include "cs-etm.h"
+
+static const char * const cs_etm_global_header_fmts[] = {
+	[CS_HEADER_VERSION]	= "	Header version		       %llx\n",
+	[CS_PMU_TYPE_CPUS]	= "	PMU type/num cpus	       %llx\n",
+	[CS_ETM_SNAPSHOT]	= "	Snapshot		       %llx\n",
+};
+
+static const char * const cs_etm_priv_fmts[] = {
+	[CS_ETM_MAGIC]		= "	Magic number		       %llx\n",
+	[CS_ETM_CPU]		= "	CPU			       %lld\n",
+	[CS_ETM_NR_TRC_PARAMS]	= "	NR_TRC_PARAMS		       %llx\n",
+	[CS_ETM_ETMCR]		= "	ETMCR			       %llx\n",
+	[CS_ETM_ETMTRACEIDR]	= "	ETMTRACEIDR		       %llx\n",
+	[CS_ETM_ETMCCER]	= "	ETMCCER			       %llx\n",
+	[CS_ETM_ETMIDR]		= "	ETMIDR			       %llx\n",
+};
+
+static const char * const cs_etmv4_priv_fmts[] = {
+	[CS_ETM_MAGIC]		= "	Magic number		       %llx\n",
+	[CS_ETM_CPU]		= "	CPU			       %lld\n",
+	[CS_ETM_NR_TRC_PARAMS]	= "	NR_TRC_PARAMS		       %llx\n",
+	[CS_ETMV4_TRCCONFIGR]	= "	TRCCONFIGR		       %llx\n",
+	[CS_ETMV4_TRCTRACEIDR]	= "	TRCTRACEIDR		       %llx\n",
+	[CS_ETMV4_TRCIDR0]	= "	TRCIDR0			       %llx\n",
+	[CS_ETMV4_TRCIDR1]	= "	TRCIDR1			       %llx\n",
+	[CS_ETMV4_TRCIDR2]	= "	TRCIDR2			       %llx\n",
+	[CS_ETMV4_TRCIDR8]	= "	TRCIDR8			       %llx\n",
+	[CS_ETMV4_TRCAUTHSTATUS] = "	TRCAUTHSTATUS		       %llx\n",
+	[CS_ETE_TRCDEVARCH]	= "	TRCDEVARCH                     %llx\n"
+};
+
+static const char * const param_unk_fmt =
+	"	Unknown parameter [%d]	       %"PRIx64"\n";
+static const char * const magic_unk_fmt =
+	"	Magic number Unknown	       %"PRIx64"\n";
+
+static int cs_etm__print_cpu_metadata_v0(u64 *val, int *offset)
+{
+	int i = *offset, j, nr_params = 0, fmt_offset;
+	u64 magic;
+
+	/* check magic value */
+	magic = val[i + CS_ETM_MAGIC];
+	if ((magic != __perf_cs_etmv3_magic) &&
+	    (magic != __perf_cs_etmv4_magic)) {
+		/* failure - note bad magic value */
+		fprintf(stdout, magic_unk_fmt, magic);
+		return -EINVAL;
+	}
+
+	/* print common header block */
+	fprintf(stdout, cs_etm_priv_fmts[CS_ETM_MAGIC], val[i++]);
+	fprintf(stdout, cs_etm_priv_fmts[CS_ETM_CPU], val[i++]);
+
+	if (magic == __perf_cs_etmv3_magic) {
+		nr_params = CS_ETM_NR_TRC_PARAMS_V0;
+		fmt_offset = CS_ETM_ETMCR;
+		/* after common block, offset format index past NR_PARAMS */
+		for (j = fmt_offset; j < nr_params + fmt_offset; j++, i++)
+			fprintf(stdout, cs_etm_priv_fmts[j], val[i]);
+	} else if (magic == __perf_cs_etmv4_magic) {
+		nr_params = CS_ETMV4_NR_TRC_PARAMS_V0;
+		fmt_offset = CS_ETMV4_TRCCONFIGR;
+		/* after common block, offset format index past NR_PARAMS */
+		for (j = fmt_offset; j < nr_params + fmt_offset; j++, i++)
+			fprintf(stdout, cs_etmv4_priv_fmts[j], val[i]);
+	}
+	*offset = i;
+	return 0;
+}
+
+static int cs_etm__print_cpu_metadata_v1(u64 *val, int *offset)
+{
+	int i = *offset, j, total_params = 0;
+	u64 magic;
+
+	magic = val[i + CS_ETM_MAGIC];
+	/* total params to print is NR_PARAMS + common block size for v1 */
+	total_params = val[i + CS_ETM_NR_TRC_PARAMS] + CS_ETM_COMMON_BLK_MAX_V1;
+
+	if (magic == __perf_cs_etmv3_magic) {
+		for (j = 0; j < total_params; j++, i++) {
+			/* if newer record - could be excess params */
+			if (j >= CS_ETM_PRIV_MAX)
+				fprintf(stdout, param_unk_fmt, j, val[i]);
+			else
+				fprintf(stdout, cs_etm_priv_fmts[j], val[i]);
+		}
+	} else if (magic == __perf_cs_etmv4_magic || magic == __perf_cs_ete_magic) {
+		/*
+		 * ETE and ETMv4 can be printed in the same block because the number of parameters
+		 * is saved and they share the list of parameter names. ETE is also only supported
+		 * in V1 files.
+		 */
+		for (j = 0; j < total_params; j++, i++) {
+			/* if newer record - could be excess params */
+			if (j >= CS_ETE_PRIV_MAX)
+				fprintf(stdout, param_unk_fmt, j, val[i]);
+			else
+				fprintf(stdout, cs_etmv4_priv_fmts[j], val[i]);
+		}
+	} else {
+		/* failure - note bad magic value and error out */
+		fprintf(stdout, magic_unk_fmt, magic);
+		return -EINVAL;
+	}
+	*offset = i;
+	return 0;
+}
+
+static void cs_etm__print_auxtrace_info(u64 *val, int num)
+{
+	int i, cpu = 0, version, err;
+
+	version = val[0];
+
+	for (i = 0; i < CS_HEADER_VERSION_MAX; i++)
+		fprintf(stdout, cs_etm_global_header_fmts[i], val[i]);
+
+	for (i = CS_HEADER_VERSION_MAX; cpu < num; cpu++) {
+		if (version == 0)
+			err = cs_etm__print_cpu_metadata_v0(val, &i);
+		else if (version == 1)
+			err = cs_etm__print_cpu_metadata_v1(val, &i);
+		if (err)
+			return;
+	}
+}
+
+/*
+ * Do some basic checks and print the auxtrace info header before calling
+ * into cs_etm__process_auxtrace_info_full() which requires OpenCSD to be
+ * linked in. This allows some basic debugging if OpenCSD is missing.
+ */
+int cs_etm__process_auxtrace_info(union perf_event *event,
+				  struct perf_session *session)
+{
+	struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
+	int event_header_size = sizeof(struct perf_event_header);
+	int num_cpu;
+	u64 *ptr = NULL;
+	u64 hdr_version;
+
+	if (auxtrace_info->header.size < (event_header_size + INFO_HEADER_SIZE))
+		return -EINVAL;
+
+	/* First the global part */
+	ptr = (u64 *) auxtrace_info->priv;
+
+	/* Look for version of the header */
+	hdr_version = ptr[0];
+	if (hdr_version > CS_HEADER_CURRENT_VERSION) {
+		pr_err("\nCS ETM Trace: Unknown Header Version = %#" PRIx64, hdr_version);
+		pr_err(", version supported <= %x\n", CS_HEADER_CURRENT_VERSION);
+		return -EINVAL;
+	}
+
+	if (dump_trace) {
+		num_cpu = ptr[CS_PMU_TYPE_CPUS] & 0xffffffff;
+		cs_etm__print_auxtrace_info(ptr, num_cpu);
+	}
+
+	return cs_etm__process_auxtrace_info_full(event, session);
+}
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index ab30591a6c6a..33303d03c2fa 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -2510,134 +2510,6 @@ static bool cs_etm__is_timeless_decoding(struct cs_etm_auxtrace *etm)
 	return timeless_decoding;
 }
 
-static const char * const cs_etm_global_header_fmts[] = {
-	[CS_HEADER_VERSION]	= "	Header version		       %llx\n",
-	[CS_PMU_TYPE_CPUS]	= "	PMU type/num cpus	       %llx\n",
-	[CS_ETM_SNAPSHOT]	= "	Snapshot		       %llx\n",
-};
-
-static const char * const cs_etm_priv_fmts[] = {
-	[CS_ETM_MAGIC]		= "	Magic number		       %llx\n",
-	[CS_ETM_CPU]		= "	CPU			       %lld\n",
-	[CS_ETM_NR_TRC_PARAMS]	= "	NR_TRC_PARAMS		       %llx\n",
-	[CS_ETM_ETMCR]		= "	ETMCR			       %llx\n",
-	[CS_ETM_ETMTRACEIDR]	= "	ETMTRACEIDR		       %llx\n",
-	[CS_ETM_ETMCCER]	= "	ETMCCER			       %llx\n",
-	[CS_ETM_ETMIDR]		= "	ETMIDR			       %llx\n",
-};
-
-static const char * const cs_etmv4_priv_fmts[] = {
-	[CS_ETM_MAGIC]		= "	Magic number		       %llx\n",
-	[CS_ETM_CPU]		= "	CPU			       %lld\n",
-	[CS_ETM_NR_TRC_PARAMS]	= "	NR_TRC_PARAMS		       %llx\n",
-	[CS_ETMV4_TRCCONFIGR]	= "	TRCCONFIGR		       %llx\n",
-	[CS_ETMV4_TRCTRACEIDR]	= "	TRCTRACEIDR		       %llx\n",
-	[CS_ETMV4_TRCIDR0]	= "	TRCIDR0			       %llx\n",
-	[CS_ETMV4_TRCIDR1]	= "	TRCIDR1			       %llx\n",
-	[CS_ETMV4_TRCIDR2]	= "	TRCIDR2			       %llx\n",
-	[CS_ETMV4_TRCIDR8]	= "	TRCIDR8			       %llx\n",
-	[CS_ETMV4_TRCAUTHSTATUS] = "	TRCAUTHSTATUS		       %llx\n",
-	[CS_ETE_TRCDEVARCH]	= "	TRCDEVARCH                     %llx\n"
-};
-
-static const char * const param_unk_fmt =
-	"	Unknown parameter [%d]	       %"PRIx64"\n";
-static const char * const magic_unk_fmt =
-	"	Magic number Unknown	       %"PRIx64"\n";
-
-static int cs_etm__print_cpu_metadata_v0(u64 *val, int *offset)
-{
-	int i = *offset, j, nr_params = 0, fmt_offset;
-	u64 magic;
-
-	/* check magic value */
-	magic = val[i + CS_ETM_MAGIC];
-	if ((magic != __perf_cs_etmv3_magic) &&
-	    (magic != __perf_cs_etmv4_magic)) {
-		/* failure - note bad magic value */
-		fprintf(stdout, magic_unk_fmt, magic);
-		return -EINVAL;
-	}
-
-	/* print common header block */
-	fprintf(stdout, cs_etm_priv_fmts[CS_ETM_MAGIC], val[i++]);
-	fprintf(stdout, cs_etm_priv_fmts[CS_ETM_CPU], val[i++]);
-
-	if (magic == __perf_cs_etmv3_magic) {
-		nr_params = CS_ETM_NR_TRC_PARAMS_V0;
-		fmt_offset = CS_ETM_ETMCR;
-		/* after common block, offset format index past NR_PARAMS */
-		for (j = fmt_offset; j < nr_params + fmt_offset; j++, i++)
-			fprintf(stdout, cs_etm_priv_fmts[j], val[i]);
-	} else if (magic == __perf_cs_etmv4_magic) {
-		nr_params = CS_ETMV4_NR_TRC_PARAMS_V0;
-		fmt_offset = CS_ETMV4_TRCCONFIGR;
-		/* after common block, offset format index past NR_PARAMS */
-		for (j = fmt_offset; j < nr_params + fmt_offset; j++, i++)
-			fprintf(stdout, cs_etmv4_priv_fmts[j], val[i]);
-	}
-	*offset = i;
-	return 0;
-}
-
-static int cs_etm__print_cpu_metadata_v1(u64 *val, int *offset)
-{
-	int i = *offset, j, total_params = 0;
-	u64 magic;
-
-	magic = val[i + CS_ETM_MAGIC];
-	/* total params to print is NR_PARAMS + common block size for v1 */
-	total_params = val[i + CS_ETM_NR_TRC_PARAMS] + CS_ETM_COMMON_BLK_MAX_V1;
-
-	if (magic == __perf_cs_etmv3_magic) {
-		for (j = 0; j < total_params; j++, i++) {
-			/* if newer record - could be excess params */
-			if (j >= CS_ETM_PRIV_MAX)
-				fprintf(stdout, param_unk_fmt, j, val[i]);
-			else
-				fprintf(stdout, cs_etm_priv_fmts[j], val[i]);
-		}
-	} else if (magic == __perf_cs_etmv4_magic || magic == __perf_cs_ete_magic) {
-		/*
-		 * ETE and ETMv4 can be printed in the same block because the number of parameters
-		 * is saved and they share the list of parameter names. ETE is also only supported
-		 * in V1 files.
-		 */
-		for (j = 0; j < total_params; j++, i++) {
-			/* if newer record - could be excess params */
-			if (j >= CS_ETE_PRIV_MAX)
-				fprintf(stdout, param_unk_fmt, j, val[i]);
-			else
-				fprintf(stdout, cs_etmv4_priv_fmts[j], val[i]);
-		}
-	} else {
-		/* failure - note bad magic value and error out */
-		fprintf(stdout, magic_unk_fmt, magic);
-		return -EINVAL;
-	}
-	*offset = i;
-	return 0;
-}
-
-static void cs_etm__print_auxtrace_info(u64 *val, int num)
-{
-	int i, cpu = 0, version, err;
-
-	version = val[0];
-
-	for (i = 0; i < CS_HEADER_VERSION_MAX; i++)
-		fprintf(stdout, cs_etm_global_header_fmts[i], val[i]);
-
-	for (i = CS_HEADER_VERSION_MAX; cpu < num; cpu++) {
-		if (version == 0)
-			err = cs_etm__print_cpu_metadata_v0(val, &i);
-		else if (version == 1)
-			err = cs_etm__print_cpu_metadata_v1(val, &i);
-		if (err)
-			return;
-	}
-}
-
 /*
  * Read a single cpu parameter block from the auxtrace_info priv block.
  *
@@ -2874,15 +2746,13 @@ static int cs_etm__queue_aux_records(struct perf_session *session)
 	return 0;
 }
 
-int cs_etm__process_auxtrace_info(union perf_event *event,
-				  struct perf_session *session)
+int cs_etm__process_auxtrace_info_full(union perf_event *event,
+				       struct perf_session *session)
 {
 	struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
 	struct cs_etm_auxtrace *etm = NULL;
 	struct int_node *inode;
-	unsigned int pmu_type;
 	int event_header_size = sizeof(struct perf_event_header);
-	int info_header_size;
 	int total_size = auxtrace_info->header.size;
 	int priv_size = 0;
 	int num_cpu, trcidr_idx;
@@ -2890,36 +2760,6 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
 	int i, j;
 	u64 *ptr = NULL;
 	u64 **metadata = NULL;
-	u64 hdr_version;
-
-	/*
-	 * sizeof(auxtrace_info_event::type) +
-	 * sizeof(auxtrace_info_event::reserved) == 8
-	 */
-	info_header_size = 8;
-
-	if (total_size < (event_header_size + info_header_size))
-		return -EINVAL;
-
-	priv_size = total_size - event_header_size - info_header_size;
-
-	/* First the global part */
-	ptr = (u64 *) auxtrace_info->priv;
-
-	/* Look for version of the header */
-	hdr_version = ptr[0];
-	if (hdr_version > CS_HEADER_CURRENT_VERSION) {
-		pr_err("\nCS ETM Trace: Unknown Header Version = %#" PRIx64, hdr_version);
-		pr_err(", version supported <= %x\n", CS_HEADER_CURRENT_VERSION);
-		return -EINVAL;
-	}
-
-	num_cpu = ptr[CS_PMU_TYPE_CPUS] & 0xffffffff;
-	pmu_type = (unsigned int) ((ptr[CS_PMU_TYPE_CPUS] >> 32) &
-				    0xffffffff);
-
-	if (dump_trace)
-		cs_etm__print_auxtrace_info(ptr, num_cpu);
 
 	/*
 	 * Create an RB tree for traceID-metadata tuple.  Since the conversion
@@ -2930,6 +2770,9 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
 	if (!traceid_list)
 		return -ENOMEM;
 
+	/* First the global part */
+	ptr = (u64 *) auxtrace_info->priv;
+	num_cpu = ptr[CS_PMU_TYPE_CPUS] & 0xffffffff;
 	metadata = zalloc(sizeof(*metadata) * num_cpu);
 	if (!metadata) {
 		err = -ENOMEM;
@@ -3008,6 +2851,7 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
 	 * The following tests if the correct number of double words was
 	 * present in the auxtrace info section.
 	 */
+	priv_size = total_size - event_header_size - INFO_HEADER_SIZE;
 	if (i * 8 != priv_size) {
 		err = -EINVAL;
 		goto err_free_metadata;
@@ -3036,7 +2880,7 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
 	etm->machine = &session->machines.host;
 
 	etm->num_cpu = num_cpu;
-	etm->pmu_type = pmu_type;
+	etm->pmu_type = (unsigned int) ((ptr[CS_PMU_TYPE_CPUS] >> 32) & 0xffffffff);
 	etm->snapshot_mode = (ptr[CS_ETM_SNAPSHOT] != 0);
 	etm->metadata = metadata;
 	etm->auxtrace_type = auxtrace_info->type;
diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h
index 401f74be98d6..5da50d5dae6b 100644
--- a/tools/perf/util/cs-etm.h
+++ b/tools/perf/util/cs-etm.h
@@ -202,9 +202,13 @@ struct cs_etm_packet_queue {
 #define CS_ETMV4_PRIV_SIZE (CS_ETMV4_PRIV_MAX * sizeof(u64))
 #define CS_ETE_PRIV_SIZE (CS_ETE_PRIV_MAX * sizeof(u64))
 
-#ifdef HAVE_CSTRACE_SUPPORT
+#define INFO_HEADER_SIZE (sizeof(((struct perf_record_auxtrace_info *)0)->type) + \
+			  sizeof(((struct perf_record_auxtrace_info *)0)->reserved__))
+
 int cs_etm__process_auxtrace_info(union perf_event *event,
 				  struct perf_session *session);
+
+#ifdef HAVE_CSTRACE_SUPPORT
 int cs_etm__get_cpu(u8 trace_chan_id, int *cpu);
 int cs_etm__get_pid_fmt(u8 trace_chan_id, u64 *pid_fmt);
 int cs_etm__etmq_set_tid(struct cs_etm_queue *etmq,
@@ -214,10 +218,12 @@ void cs_etm__etmq_set_traceid_queue_timestamp(struct cs_etm_queue *etmq,
 					      u8 trace_chan_id);
 struct cs_etm_packet_queue
 *cs_etm__etmq_get_packet_queue(struct cs_etm_queue *etmq, u8 trace_chan_id);
+int cs_etm__process_auxtrace_info_full(union perf_event *event __maybe_unused,
+				       struct perf_session *session __maybe_unused);
 #else
 static inline int
-cs_etm__process_auxtrace_info(union perf_event *event __maybe_unused,
-			      struct perf_session *session __maybe_unused)
+cs_etm__process_auxtrace_info_full(union perf_event *event __maybe_unused,
+				   struct perf_session *session __maybe_unused)
 {
 	pr_err("\nCS ETM Trace: OpenCSD is not linked in, please recompile with CORESIGHT=1\n");
 	return -1;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/5] perf: cs-etm: Print auxtrace info even if OpenCSD isn't linked
  2022-12-12 15:55 [PATCH 0/5] perf: cs-etm: Print auxtrace info even if OpenCSD isn't linked James Clark
                   ` (4 preceding siblings ...)
  2022-12-12 15:55 ` [PATCH 5/5] perf: cs-etm: Print auxtrace info even if OpenCSD isn't linked James Clark
@ 2022-12-12 19:50 ` Arnaldo Carvalho de Melo
  5 siblings, 0 replies; 7+ messages in thread
From: Arnaldo Carvalho de Melo @ 2022-12-12 19:50 UTC (permalink / raw)
  To: James Clark
  Cc: linux-perf-users, Al.Grant, Peter Zijlstra, Ingo Molnar,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	John Garry, Will Deacon, Mike Leach, Leo Yan, Mathieu Poirier,
	Suzuki K Poulose, linux-kernel, linux-arm-kernel, coresight

Em Mon, Dec 12, 2022 at 03:55:08PM +0000, James Clark escreveu:
> The auxtrace info header can be useful for debugging, and at the
> moment it's possible to record a file without OpenCSD linked but
> not view the header even though it should be possible to do.
> 
> This patchset tidies up some of the related functions and
> improves some of the error messages before making the above
> possible in the last commit.
> 
> Testing done:
> 
>  * Compiled on x86 and Arm both with and without CORESIGHT=1
>  * Ran the Coresight tests
> 
> Applies to perf/core (0c3852adae8)

Thanks, applied.

- Arnaldo

 
> James Clark (5):
>   perf: cs-etm: Print unknown header version as an error
>   perf: cs-etm: Remove unused stub methods
>   perf: cs-etm: Tidy up auxtrace info header printing
>   perf: cs-etm: Cleanup cs_etm__process_auxtrace_info()
>   perf: cs-etm: Print auxtrace info even if OpenCSD isn't linked
> 
>  tools/perf/util/Build         |   1 +
>  tools/perf/util/cs-etm-base.c | 174 ++++++++++++++++++++++++++++
>  tools/perf/util/cs-etm.c      | 208 +++-------------------------------
>  tools/perf/util/cs-etm.h      |  46 ++------
>  4 files changed, 200 insertions(+), 229 deletions(-)
>  create mode 100644 tools/perf/util/cs-etm-base.c
> 
> -- 
> 2.25.1

-- 

- Arnaldo

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-12-12 19:51 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-12 15:55 [PATCH 0/5] perf: cs-etm: Print auxtrace info even if OpenCSD isn't linked James Clark
2022-12-12 15:55 ` [PATCH 1/5] perf: cs-etm: Print unknown header version as an error James Clark
2022-12-12 15:55 ` [PATCH 2/5] perf: cs-etm: Remove unused stub methods James Clark
2022-12-12 15:55 ` [PATCH 3/5] perf: cs-etm: Tidy up auxtrace info header printing James Clark
2022-12-12 15:55 ` [PATCH 4/5] perf: cs-etm: Cleanup cs_etm__process_auxtrace_info() James Clark
2022-12-12 15:55 ` [PATCH 5/5] perf: cs-etm: Print auxtrace info even if OpenCSD isn't linked James Clark
2022-12-12 19:50 ` [PATCH 0/5] " Arnaldo Carvalho de Melo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).