diff mbox series

[v1,9/9] perf arm-spe: Dump metadata with version 2

Message ID 20240827164417.3309560-10-leo.yan@arm.com (mailing list archive)
State New, archived
Headers show
Series perf arm-spe: Introduce metadata version 2 | expand

Commit Message

Leo Yan Aug. 27, 2024, 4:44 p.m. UTC
This commit dumps metadata with version 2. It uses two string arrays
metadata_hdr_fmts and metadata_per_cpu_fmts as string formats for the
header and per CPU data respectively, and the arm_spe_print_info()
function is enhanced to support dumping metadata with the version 2
format.

After:

  0 0 0x4a8 [0x170]: PERF_RECORD_AUXTRACE_INFO type: 4
  PMU Type           :13
  Version            :2
  Num of CPUs        :8
    CPU #            :0
    MIDR             :0x410fd801
    Bound PMU Type   :-1
    Min Interval     :0
    Load Data Source :0
    CPU #            :1
    MIDR             :0x410fd801
    Bound PMU Type   :-1
    Min Interval     :0
    Load Data Source :0
    CPU #            :2
    MIDR             :0x410fd870
    Bound PMU Type   :13
    Min Interval     :1024
    Load Data Source :1
    CPU #            :3
    MIDR             :0x410fd870
    Bound PMU Type   :13
    Min Interval     :1024
    Load Data Source :1
    CPU #            :4
    MIDR             :0x410fd870
    Bound PMU Type   :13
    Min Interval     :1024
    Load Data Source :1
    CPU #            :5
    MIDR             :0x410fd870
    Bound PMU Type   :13
    Min Interval     :1024
    Load Data Source :1
    CPU #            :6
    MIDR             :0x410fd850
    Bound PMU Type   :14
    Min Interval     :1024
    Load Data Source :1
    CPU #            :7
    MIDR             :0x410fd850
    Bound PMU Type   :14
    Min Interval     :1024
    Load Data Source :1

Signed-off-by: Leo Yan <leo.yan@arm.com>
---
 tools/perf/util/arm-spe.c | 43 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 38 insertions(+), 5 deletions(-)

Comments

James Clark Aug. 28, 2024, 4:20 p.m. UTC | #1
On 27/08/2024 5:44 pm, Leo Yan wrote:
> This commit dumps metadata with version 2. It uses two string arrays
> metadata_hdr_fmts and metadata_per_cpu_fmts as string formats for the
> header and per CPU data respectively, and the arm_spe_print_info()
> function is enhanced to support dumping metadata with the version 2
> format.
> 
> After:
> 
>    0 0 0x4a8 [0x170]: PERF_RECORD_AUXTRACE_INFO type: 4
>    PMU Type           :13
>    Version            :2
>    Num of CPUs        :8
>      CPU #            :0
>      MIDR             :0x410fd801
>      Bound PMU Type   :-1
>      Min Interval     :0
>      Load Data Source :0
>      CPU #            :1
>      MIDR             :0x410fd801
>      Bound PMU Type   :-1
>      Min Interval     :0
>      Load Data Source :0
>      CPU #            :2
>      MIDR             :0x410fd870
>      Bound PMU Type   :13
>      Min Interval     :1024
>      Load Data Source :1
>      CPU #            :3
>      MIDR             :0x410fd870
>      Bound PMU Type   :13
>      Min Interval     :1024
>      Load Data Source :1
>      CPU #            :4
>      MIDR             :0x410fd870
>      Bound PMU Type   :13
>      Min Interval     :1024
>      Load Data Source :1
>      CPU #            :5
>      MIDR             :0x410fd870
>      Bound PMU Type   :13
>      Min Interval     :1024
>      Load Data Source :1
>      CPU #            :6
>      MIDR             :0x410fd850
>      Bound PMU Type   :14
>      Min Interval     :1024
>      Load Data Source :1
>      CPU #            :7
>      MIDR             :0x410fd850
>      Bound PMU Type   :14
>      Min Interval     :1024
>      Load Data Source :1
> 
> Signed-off-by: Leo Yan <leo.yan@arm.com>
> ---
>   tools/perf/util/arm-spe.c | 43 ++++++++++++++++++++++++++++++++++-----
>   1 file changed, 38 insertions(+), 5 deletions(-)
> 
> diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
> index 87cf06db765b..be34d4c4306a 100644
> --- a/tools/perf/util/arm-spe.c
> +++ b/tools/perf/util/arm-spe.c
> @@ -1067,16 +1067,49 @@ static bool arm_spe_evsel_is_auxtrace(struct perf_session *session __maybe_unuse
>   	return strstarts(evsel->name, ARM_SPE_PMU_NAME);
>   }
>   
> -static const char * const arm_spe_info_fmts[] = {
> -	[ARM_SPE_PMU_TYPE]		= "  PMU Type           %"PRId64"\n",
> +static const char * const metadata_hdr_fmts[] = {
> +	[ARM_SPE_PMU_TYPE]		= "  PMU Type           :%"PRId64"\n",
> +	[ARM_SPE_HEADER_VERSION]	= "  Version            :%"PRId64"\n",
> +	[ARM_SPE_CPU_NUM]		= "  Num of CPUs        :%"PRId64"\n",
>   };
>   
> -static void arm_spe_print_info(__u64 *arr)
> +static const char * const metadata_per_cpu_fmts[] = {
> +	[ARM_SPE_CPU]			= "    CPU #            :%"PRId64"\n",
> +	[ARM_SPE_CPU_MIDR]		= "    MIDR             :0x%"PRIx64"\n",
> +	[ARM_SPE_CPU_PMU_TYPE]		= "    Bound PMU Type   :%"PRId64"\n",
> +	[ARM_SPE_CAP_MIN_IVAL]		= "    Min Interval     :%"PRId64"\n",
> +	[ARM_SPE_CAP_LDS]		= "    Load Data Source :%"PRId64"\n",
> +};
> +
> +static void arm_spe_print_info(struct arm_spe *spe, __u64 *arr)
>   {
> +	unsigned int i, cpu, header_size, cpu_num, per_cpu_size;
> +
>   	if (!dump_trace)
>   		return;
>   
> -	fprintf(stdout, arm_spe_info_fmts[ARM_SPE_PMU_TYPE], arr[ARM_SPE_PMU_TYPE]);
> +	if (spe->metadata_ver == 1) {
> +		cpu_num = 0;
> +		header_size = ARM_SPE_AUXTRACE_V1_PRIV_MAX;
> +		per_cpu_size = 0;
> +	} else if (spe->metadata_ver == 2) {

Assuming future version updates are backwards compatible and only add 
new info this should be spe->metadata_ver >= 2, otherwise version bumps 
end up causing errors when files get passed around.

I know there are arguments about what should and shouldn't be supported 
when opening new files on old perfs, but in this case it's easy to only 
add new info to the aux header and leave the old stuff intact.

> +		cpu_num = arr[ARM_SPE_CPU_NUM];
> +		header_size = ARM_SPE_AUXTRACE_V2_PRIV_MAX;
> +		per_cpu_size = ARM_SPE_AUXTRACE_V2_PRIV_PER_CPU_MAX;

I think for coresight we also save the size of each per-cpu block rather 
than use a constant, that way new items can be appended without breaking 
readers.

That kind of leads to another point that this mechanism is mostly 
duplicated from coresight. It saves a main header version, then per-cpu 
groups of variable size with named elements. I'm not saying we should 
definitely try to share the code, but it's worth keeping in mind.

> +	} else {
> +		pr_err("Cannot support metadata ver: %ld\n", spe->metadata_ver);
> +		return;
> +	}
> +
> +	for (i = 0; i < header_size; i++)
> +		fprintf(stdout, metadata_hdr_fmts[i], arr[i]);
> +
> +	arr += header_size;
> +	for (cpu = 0; cpu < cpu_num; cpu++) {
> +		for (i = 0; i < per_cpu_size; i++)
> +			fprintf(stdout, metadata_per_cpu_fmts[i], arr[i]);
> +		arr += per_cpu_size;
> +	}
>   }
>   
>   static void arm_spe_set_event_name(struct evlist *evlist, u64 id,
> @@ -1383,7 +1416,7 @@ int arm_spe_process_auxtrace_info(union perf_event *event,
>   	spe->auxtrace.evsel_is_auxtrace = arm_spe_evsel_is_auxtrace;
>   	session->auxtrace = &spe->auxtrace;
>   
> -	arm_spe_print_info(&auxtrace_info->priv[0]);
> +	arm_spe_print_info(spe, &auxtrace_info->priv[0]);
>   
>   	if (dump_trace)
>   		return 0;
Leo Yan Aug. 30, 2024, 7:54 a.m. UTC | #2
On 8/28/24 17:20, James Clark wrote:
>> +static void arm_spe_print_info(struct arm_spe *spe, __u64 *arr)
>>   {
>> +     unsigned int i, cpu, header_size, cpu_num, per_cpu_size;
>> +
>>       if (!dump_trace)
>>               return;
>>
>> -     fprintf(stdout, arm_spe_info_fmts[ARM_SPE_PMU_TYPE], arr[ARM_SPE_PMU_TYPE]);
>> +     if (spe->metadata_ver == 1) {
>> +             cpu_num = 0;
>> +             header_size = ARM_SPE_AUXTRACE_V1_PRIV_MAX;
>> +             per_cpu_size = 0;
>> +     } else if (spe->metadata_ver == 2) {
> 
> Assuming future version updates are backwards compatible and only add
> new info this should be spe->metadata_ver >= 2, otherwise version bumps
> end up causing errors when files get passed around.
> 
> I know there are arguments about what should and shouldn't be supported
> when opening new files on old perfs, but in this case it's easy to only
> add new info to the aux header and leave the old stuff intact.
> 
>> +             cpu_num = arr[ARM_SPE_CPU_NUM];
>> +             header_size = ARM_SPE_AUXTRACE_V2_PRIV_MAX;
>> +             per_cpu_size = ARM_SPE_AUXTRACE_V2_PRIV_PER_CPU_MAX;
> 
> I think for coresight we also save the size of each per-cpu block rather
> than use a constant, that way new items can be appended without breaking
> readers.

Good point for adding a 'size' field for each per-cpu block.

My understanding is we need to make the metadata format to be self-described.
E.g. the metadata header contains the size for itself, and every per CPU
metadata block also contains a 'size' field.  Based on this, a general code
can be used to processing different metadata versions.
  
> That kind of leads to another point that this mechanism is mostly
> duplicated from coresight. It saves a main header version, then per-cpu
> groups of variable size with named elements. I'm not saying we should
> definitely try to share the code, but it's worth keeping in mind.

Agreed. I will refine a bit, for better matching this direction.

Thanks for suggestion.

Leo
diff mbox series

Patch

diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
index 87cf06db765b..be34d4c4306a 100644
--- a/tools/perf/util/arm-spe.c
+++ b/tools/perf/util/arm-spe.c
@@ -1067,16 +1067,49 @@  static bool arm_spe_evsel_is_auxtrace(struct perf_session *session __maybe_unuse
 	return strstarts(evsel->name, ARM_SPE_PMU_NAME);
 }
 
-static const char * const arm_spe_info_fmts[] = {
-	[ARM_SPE_PMU_TYPE]		= "  PMU Type           %"PRId64"\n",
+static const char * const metadata_hdr_fmts[] = {
+	[ARM_SPE_PMU_TYPE]		= "  PMU Type           :%"PRId64"\n",
+	[ARM_SPE_HEADER_VERSION]	= "  Version            :%"PRId64"\n",
+	[ARM_SPE_CPU_NUM]		= "  Num of CPUs        :%"PRId64"\n",
 };
 
-static void arm_spe_print_info(__u64 *arr)
+static const char * const metadata_per_cpu_fmts[] = {
+	[ARM_SPE_CPU]			= "    CPU #            :%"PRId64"\n",
+	[ARM_SPE_CPU_MIDR]		= "    MIDR             :0x%"PRIx64"\n",
+	[ARM_SPE_CPU_PMU_TYPE]		= "    Bound PMU Type   :%"PRId64"\n",
+	[ARM_SPE_CAP_MIN_IVAL]		= "    Min Interval     :%"PRId64"\n",
+	[ARM_SPE_CAP_LDS]		= "    Load Data Source :%"PRId64"\n",
+};
+
+static void arm_spe_print_info(struct arm_spe *spe, __u64 *arr)
 {
+	unsigned int i, cpu, header_size, cpu_num, per_cpu_size;
+
 	if (!dump_trace)
 		return;
 
-	fprintf(stdout, arm_spe_info_fmts[ARM_SPE_PMU_TYPE], arr[ARM_SPE_PMU_TYPE]);
+	if (spe->metadata_ver == 1) {
+		cpu_num = 0;
+		header_size = ARM_SPE_AUXTRACE_V1_PRIV_MAX;
+		per_cpu_size = 0;
+	} else if (spe->metadata_ver == 2) {
+		cpu_num = arr[ARM_SPE_CPU_NUM];
+		header_size = ARM_SPE_AUXTRACE_V2_PRIV_MAX;
+		per_cpu_size = ARM_SPE_AUXTRACE_V2_PRIV_PER_CPU_MAX;
+	} else {
+		pr_err("Cannot support metadata ver: %ld\n", spe->metadata_ver);
+		return;
+	}
+
+	for (i = 0; i < header_size; i++)
+		fprintf(stdout, metadata_hdr_fmts[i], arr[i]);
+
+	arr += header_size;
+	for (cpu = 0; cpu < cpu_num; cpu++) {
+		for (i = 0; i < per_cpu_size; i++)
+			fprintf(stdout, metadata_per_cpu_fmts[i], arr[i]);
+		arr += per_cpu_size;
+	}
 }
 
 static void arm_spe_set_event_name(struct evlist *evlist, u64 id,
@@ -1383,7 +1416,7 @@  int arm_spe_process_auxtrace_info(union perf_event *event,
 	spe->auxtrace.evsel_is_auxtrace = arm_spe_evsel_is_auxtrace;
 	session->auxtrace = &spe->auxtrace;
 
-	arm_spe_print_info(&auxtrace_info->priv[0]);
+	arm_spe_print_info(spe, &auxtrace_info->priv[0]);
 
 	if (dump_trace)
 		return 0;