Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf arm_spe: Allow parsing both data source and events

Current code skips to parse events after generating data source. The
reason is the data source packets have cache and snooping related info,
the afterwards event packets might contain duplicate info.

This commit changes to continue parsing the events after data source
analysis. If data source does not give out memory level and snooping
types, then the event info is used to synthesize the related fields.

As a result, both the peer snoop option ('-d peer') and hitm options
('-d tot/lcl/rmt') are supported by Arm SPE in 'perf c2c'.

Reviewed-by: James Clark <james.clark@linaro.org>
Signed-off-by: Leo Yan <leo.yan@arm.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ali Saidi <alisaidi@amazon.com>
Cc: German Gomez <german.gomez@arm.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Leo Yan and committed by
Arnaldo Carvalho de Melo
d120cb34 d5105689

+44 -29
+44 -29
tools/perf/util/arm-spe.c
··· 900 900 { 901 901 struct arm_spe *spe = speq->spe; 902 902 903 - if (data_src->mem_op == PERF_MEM_OP_LOAD) 904 - arm_spe__synth_ld_memory_level(record, data_src); 905 - if (data_src->mem_op == PERF_MEM_OP_STORE) 906 - arm_spe__synth_st_memory_level(record, data_src); 903 + /* 904 + * The data source packet contains more info for cache levels for 905 + * peer snooping. So respect the memory level if has been set by 906 + * data source parsing. 907 + */ 908 + if (!data_src->mem_lvl) { 909 + if (data_src->mem_op == PERF_MEM_OP_LOAD) 910 + arm_spe__synth_ld_memory_level(record, data_src); 911 + if (data_src->mem_op == PERF_MEM_OP_STORE) 912 + arm_spe__synth_st_memory_level(record, data_src); 913 + } 907 914 908 915 if (!data_src->mem_lvl) { 909 916 data_src->mem_lvl = PERF_MEM_LVL_NA; 910 917 data_src->mem_lvl_num = PERF_MEM_LVLNUM_NA; 911 918 } 912 919 913 - if (record->type & ARM_SPE_DATA_SNOOPED) { 914 - if (record->type & ARM_SPE_HITM) 915 - data_src->mem_snoop = PERF_MEM_SNOOP_HITM; 916 - else 917 - data_src->mem_snoop = PERF_MEM_SNOOP_HIT; 918 - } else { 919 - u64 *metadata = arm_spe__get_metadata_by_cpu(spe, speq->cpu); 920 + /* 921 + * If 'mem_snoop' has been set by data source packet, skip to set 922 + * it at here. 923 + */ 924 + if (!data_src->mem_snoop) { 925 + if (record->type & ARM_SPE_DATA_SNOOPED) { 926 + if (record->type & ARM_SPE_HITM) 927 + data_src->mem_snoop = PERF_MEM_SNOOP_HITM; 928 + else 929 + data_src->mem_snoop = PERF_MEM_SNOOP_HIT; 930 + } else { 931 + u64 *metadata = 932 + arm_spe__get_metadata_by_cpu(spe, speq->cpu); 920 933 921 - /* 922 - * Set NA ("Not available") mode if no meta data or the 923 - * SNOOPED event is not supported. 924 - */ 925 - if (!metadata || 926 - !(metadata[ARM_SPE_CAP_EVENT_FILTER] & ARM_SPE_DATA_SNOOPED)) 927 - data_src->mem_snoop = PERF_MEM_SNOOP_NA; 928 - else 929 - data_src->mem_snoop = PERF_MEM_SNOOP_NONE; 934 + /* 935 + * Set NA ("Not available") mode if no meta data or the 936 + * SNOOPED event is not supported. 937 + */ 938 + if (!metadata || 939 + !(metadata[ARM_SPE_CAP_EVENT_FILTER] & ARM_SPE_DATA_SNOOPED)) 940 + data_src->mem_snoop = PERF_MEM_SNOOP_NA; 941 + else 942 + data_src->mem_snoop = PERF_MEM_SNOOP_NONE; 943 + } 930 944 } 931 945 932 - if (record->type & ARM_SPE_REMOTE_ACCESS) 933 - data_src->mem_remote = PERF_MEM_REMOTE_REMOTE; 946 + if (!data_src->mem_remote) { 947 + if (record->type & ARM_SPE_REMOTE_ACCESS) 948 + data_src->mem_remote = PERF_MEM_REMOTE_REMOTE; 949 + } 934 950 } 935 951 936 - static bool arm_spe__synth_ds(struct arm_spe_queue *speq, 952 + static void arm_spe__synth_ds(struct arm_spe_queue *speq, 937 953 const struct arm_spe_record *record, 938 954 union perf_mem_data_src *data_src) 939 955 { ··· 968 952 } else { 969 953 metadata = arm_spe__get_metadata_by_cpu(spe, speq->cpu); 970 954 if (!metadata) 971 - return false; 955 + return; 972 956 973 957 midr = metadata[ARM_SPE_CPU_MIDR]; 974 958 } 975 959 976 960 for (i = 0; i < ARRAY_SIZE(data_source_handles); i++) { 977 961 if (is_midr_in_range_list(midr, data_source_handles[i].midr_ranges)) { 978 - data_source_handles[i].ds_synth(record, data_src); 979 - return true; 962 + return data_source_handles[i].ds_synth(record, data_src); 980 963 } 981 964 } 982 965 983 - return false; 966 + return; 984 967 } 985 968 986 969 static union perf_mem_data_src ··· 999 984 else 1000 985 return data_src; 1001 986 1002 - if (!arm_spe__synth_ds(speq, record, &data_src)) 1003 - arm_spe__synth_memory_level(speq, record, &data_src); 987 + arm_spe__synth_ds(speq, record, &data_src); 988 + arm_spe__synth_memory_level(speq, record, &data_src); 1004 989 1005 990 if (record->type & (ARM_SPE_TLB_ACCESS | ARM_SPE_TLB_MISS)) { 1006 991 data_src.mem_dtlb = PERF_MEM_TLB_WK;