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

perf cs-etm: Move mapping of Trace ID and cpu into helper function

The information to associate Trace ID and CPU will be changing.

Drivers will start outputting this as a hardware ID packet in the data
file which if present will be used in preference to the AUXINFO values.

To prepare for this we provide a helper functions to do the individual ID
mapping, and one to extract the IDs from the completed metadata blocks.

Reviewed-by: James Clark <james.clark@arm.com>
Signed-off-by: Mike Leach <mike.leach@linaro.org>
Acked-by: Suzuki Poulouse <suzuki.poulose@arm.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Darren Hart <darren@os.amperecomputing.com>
Cc: Ganapatrao Kulkarni <gankulkarni@os.amperecomputing.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Will Deacon <will@kernel.org>
Cc: coresight@lists.linaro.org
Cc: linux-arm-kernel@lists.infradead.org
Link: https://lore.kernel.org/r/20230331055645.26918-2-mike.leach@linaro.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Mike Leach and committed by
Arnaldo Carvalho de Melo
09277295 84c3a2bb

+79 -35
+5
tools/include/linux/coresight-pmu.h
··· 7 7 #ifndef _LINUX_CORESIGHT_PMU_H 8 8 #define _LINUX_CORESIGHT_PMU_H 9 9 10 + #include <linux/bits.h> 11 + 10 12 #define CORESIGHT_ETM_PMU_NAME "cs_etm" 11 13 #define CORESIGHT_ETM_PMU_SEED 0x10 14 + 15 + /* CoreSight trace ID is currently the bottom 7 bits of the value */ 16 + #define CORESIGHT_TRACE_ID_VAL_MASK GENMASK(6, 0) 12 17 13 18 /* 14 19 * Below are the definition of bit offsets for perf option, and works as
+2 -1
tools/perf/util/cs-etm-base.c
··· 148 148 for (i = CS_HEADER_VERSION_MAX; cpu < num; cpu++) { 149 149 if (version == 0) 150 150 err = cs_etm__print_cpu_metadata_v0(val, &i); 151 - else if (version == 1) 151 + /* printing same for both, but value bit flags added on v2 */ 152 + else if ((version == 1) || (version == 2)) 152 153 err = cs_etm__print_cpu_metadata_v1(val, &i); 153 154 if (err) 154 155 return;
+60 -32
tools/perf/util/cs-etm.c
··· 196 196 return 0; 197 197 } 198 198 199 + static int cs_etm__map_trace_id(u8 trace_chan_id, u64 *cpu_metadata) 200 + { 201 + struct int_node *inode; 202 + 203 + /* Get an RB node for this CPU */ 204 + inode = intlist__findnew(traceid_list, trace_chan_id); 205 + 206 + /* Something went wrong, no need to continue */ 207 + if (!inode) 208 + return -ENOMEM; 209 + 210 + /* 211 + * The node for that CPU should not be taken. 212 + * Back out if that's the case. 213 + */ 214 + if (inode->priv) 215 + return -EINVAL; 216 + 217 + /* All good, associate the traceID with the metadata pointer */ 218 + inode->priv = cpu_metadata; 219 + 220 + return 0; 221 + } 222 + 199 223 void cs_etm__etmq_set_traceid_queue_timestamp(struct cs_etm_queue *etmq, 200 224 u8 trace_chan_id) 201 225 { ··· 2828 2804 return true; 2829 2805 } 2830 2806 2807 + /* map trace ids to correct metadata block, from information in metadata */ 2808 + static int cs_etm__map_trace_ids_metadata(int num_cpu, u64 **metadata) 2809 + { 2810 + u64 cs_etm_magic; 2811 + u8 trace_chan_id; 2812 + int i, err; 2813 + 2814 + for (i = 0; i < num_cpu; i++) { 2815 + cs_etm_magic = metadata[i][CS_ETM_MAGIC]; 2816 + switch (cs_etm_magic) { 2817 + case __perf_cs_etmv3_magic: 2818 + trace_chan_id = (u8)((metadata[i][CS_ETM_ETMTRACEIDR]) & 2819 + CORESIGHT_TRACE_ID_VAL_MASK); 2820 + break; 2821 + case __perf_cs_etmv4_magic: 2822 + case __perf_cs_ete_magic: 2823 + trace_chan_id = (u8)((metadata[i][CS_ETMV4_TRCTRACEIDR]) & 2824 + CORESIGHT_TRACE_ID_VAL_MASK); 2825 + break; 2826 + default: 2827 + /* unknown magic number */ 2828 + return -EINVAL; 2829 + } 2830 + err = cs_etm__map_trace_id(trace_chan_id, metadata[i]); 2831 + if (err) 2832 + return err; 2833 + } 2834 + return 0; 2835 + } 2836 + 2831 2837 int cs_etm__process_auxtrace_info_full(union perf_event *event, 2832 2838 struct perf_session *session) 2833 2839 { 2834 2840 struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info; 2835 2841 struct cs_etm_auxtrace *etm = NULL; 2836 - struct int_node *inode; 2837 2842 struct perf_record_time_conv *tc = &session->time_conv; 2838 2843 int event_header_size = sizeof(struct perf_event_header); 2839 2844 int total_size = auxtrace_info->header.size; 2840 2845 int priv_size = 0; 2841 - int num_cpu, trcidr_idx; 2846 + int num_cpu; 2842 2847 int err = 0; 2843 2848 int i, j; 2844 2849 u64 *ptr = NULL; ··· 2906 2853 cs_etm__create_meta_blk(ptr, &i, 2907 2854 CS_ETM_PRIV_MAX, 2908 2855 CS_ETM_NR_TRC_PARAMS_V0); 2909 - 2910 - /* The traceID is our handle */ 2911 - trcidr_idx = CS_ETM_ETMTRACEIDR; 2912 - 2913 2856 } else if (ptr[i] == __perf_cs_etmv4_magic) { 2914 2857 metadata[j] = 2915 2858 cs_etm__create_meta_blk(ptr, &i, 2916 2859 CS_ETMV4_PRIV_MAX, 2917 2860 CS_ETMV4_NR_TRC_PARAMS_V0); 2918 - 2919 - /* The traceID is our handle */ 2920 - trcidr_idx = CS_ETMV4_TRCTRACEIDR; 2921 2861 } else if (ptr[i] == __perf_cs_ete_magic) { 2922 2862 metadata[j] = cs_etm__create_meta_blk(ptr, &i, CS_ETE_PRIV_MAX, -1); 2923 - 2924 - /* ETE shares first part of metadata with ETMv4 */ 2925 - trcidr_idx = CS_ETMV4_TRCTRACEIDR; 2926 2863 } else { 2927 2864 ui__error("CS ETM Trace: Unrecognised magic number %#"PRIx64". File could be from a newer version of perf.\n", 2928 2865 ptr[i]); ··· 2924 2881 err = -ENOMEM; 2925 2882 goto err_free_metadata; 2926 2883 } 2927 - 2928 - /* Get an RB node for this CPU */ 2929 - inode = intlist__findnew(traceid_list, metadata[j][trcidr_idx]); 2930 - 2931 - /* Something went wrong, no need to continue */ 2932 - if (!inode) { 2933 - err = -ENOMEM; 2934 - goto err_free_metadata; 2935 - } 2936 - 2937 - /* 2938 - * The node for that CPU should not be taken. 2939 - * Back out if that's the case. 2940 - */ 2941 - if (inode->priv) { 2942 - err = -EINVAL; 2943 - goto err_free_metadata; 2944 - } 2945 - /* All good, associate the traceID with the metadata pointer */ 2946 - inode->priv = metadata[j]; 2947 2884 } 2948 2885 2949 2886 /* ··· 3014 2991 etm->tc.cap_user_time_short = tc->cap_user_time_short; 3015 2992 } 3016 2993 err = cs_etm__synth_events(etm, session); 2994 + if (err) 2995 + goto err_delete_thread; 2996 + 2997 + /* before aux records are queued, need to map metadata to trace IDs */ 2998 + err = cs_etm__map_trace_ids_metadata(num_cpu, metadata); 3017 2999 if (err) 3018 3000 goto err_delete_thread; 3019 3001
+12 -2
tools/perf/util/cs-etm.h
··· 29 29 /* 30 30 * Update the version for new format. 31 31 * 32 - * New version 1 format adds a param count to the per cpu metadata. 32 + * Version 1: format adds a param count to the per cpu metadata. 33 33 * This allows easy adding of new metadata parameters. 34 34 * Requires that new params always added after current ones. 35 35 * Also allows client reader to handle file versions that are different by 36 36 * checking the number of params in the file vs the number expected. 37 + * 38 + * Version 2: Drivers will use PERF_RECORD_AUX_OUTPUT_HW_ID to output 39 + * CoreSight Trace ID. ...TRACEIDR metadata will be set to legacy values 40 + * but with addition flags. 37 41 */ 38 - #define CS_HEADER_CURRENT_VERSION 1 42 + #define CS_HEADER_CURRENT_VERSION 2 39 43 40 44 /* Beginning of header common to both ETMv3 and V4 */ 41 45 enum { ··· 100 96 CS_ETE_TS_SOURCE, 101 97 CS_ETE_PRIV_MAX 102 98 }; 99 + 100 + /* 101 + * Check for valid CoreSight trace ID. If an invalid value is present in the metadata, 102 + * then IDs are present in the hardware ID packet in the data file. 103 + */ 104 + #define CS_IS_VALID_TRACE_ID(id) ((id > 0) && (id < 0x70)) 103 105 104 106 /* 105 107 * ETMv3 exception encoding number: