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

Configure Feed

Select the types of activity you want to include in your feed.

perf: cs-etm: Allocate queues for all CPUs

Make cs_etm__setup_queue() setup a queue even if it's empty, and
pre-allocate queues based on the max CPU that was recorded. In per-CPU
mode aux queues are indexed based on CPU ID even if all CPUs aren't
recorded, sparse queue arrays aren't used.

This will allow HW_IDs to be saved even if no aux data was received in
that queue without having to call cs_etm__setup_queue() from two
different places.

Reviewed-by: Mike Leach <mike.leach@linaro.org>
Signed-off-by: James Clark <james.clark@arm.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexandre Torgue <alexandre.torgue@foss.st.com>
Cc: Anshuman Khandual <anshuman.khandual@arm.com>
Cc: Ganapatrao Kulkarni <gankulkarni@os.amperecomputing.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@linux.dev>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20240722101202.26915-3-james.clark@linaro.org
Signed-off-by: James Clark <james.clark@linaro.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

James Clark and committed by
Arnaldo Carvalho de Melo
57880a79 b6aa0de9

+25 -28
+25 -28
tools/perf/util/cs-etm.c
··· 1062 1062 1063 1063 static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm, 1064 1064 struct auxtrace_queue *queue, 1065 - unsigned int queue_nr, enum cs_etm_format format) 1065 + unsigned int queue_nr) 1066 1066 { 1067 1067 struct cs_etm_queue *etmq = queue->priv; 1068 1068 1069 - if (etmq && format != etmq->format) { 1070 - pr_err("CS_ETM: mixed formatted and unformatted trace not supported\n"); 1071 - return -EINVAL; 1072 - } 1073 - 1074 - if (list_empty(&queue->head) || etmq) 1069 + if (etmq) 1075 1070 return 0; 1076 1071 1077 1072 etmq = cs_etm__alloc_queue(); ··· 1079 1084 etmq->queue_nr = queue_nr; 1080 1085 queue->cpu = queue_nr; /* Placeholder, may be reset to -1 in per-thread mode */ 1081 1086 etmq->offset = 0; 1082 - etmq->format = format; 1083 1087 1084 1088 return 0; 1085 1089 } ··· 2766 2772 if (err) 2767 2773 return err; 2768 2774 2769 - /* 2770 - * Knowing if the trace is formatted or not requires a lookup of 2771 - * the aux record so only works in non-piped mode where data is 2772 - * queued in cs_etm__queue_aux_records(). Always assume 2773 - * formatted in piped mode (true). 2774 - */ 2775 - err = cs_etm__setup_queue(etm, &etm->queues.queue_array[idx], 2776 - idx, FORMATTED); 2777 - if (err) 2778 - return err; 2779 - 2780 2775 if (dump_trace) 2781 2776 if (auxtrace_buffer__get_data(buffer, fd)) { 2782 2777 cs_etm__dump_event(etm->queues.queue_array[idx].priv, buffer); ··· 2882 2899 struct perf_record_auxtrace *auxtrace_event; 2883 2900 union perf_event auxtrace_fragment; 2884 2901 __u64 aux_offset, aux_size; 2885 - __u32 idx; 2886 2902 enum cs_etm_format format; 2887 2903 2888 2904 struct cs_etm_auxtrace *etm = container_of(session->auxtrace, ··· 2948 2966 2949 2967 if (aux_offset >= auxtrace_event->offset && 2950 2968 aux_offset + aux_size <= auxtrace_event->offset + auxtrace_event->size) { 2969 + struct cs_etm_queue *etmq = etm->queues.queue_array[auxtrace_event->idx].priv; 2970 + 2951 2971 /* 2952 2972 * If this AUX event was inside this buffer somewhere, create a new auxtrace event 2953 2973 * based on the sizes of the aux event, and queue that fragment. ··· 2966 2982 if (err) 2967 2983 return err; 2968 2984 2969 - idx = auxtrace_event->idx; 2970 2985 format = (aux_event->flags & PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW) ? 2971 2986 UNFORMATTED : FORMATTED; 2972 - 2973 - return cs_etm__setup_queue(etm, &etm->queues.queue_array[idx], idx, format); 2987 + if (etmq->format != UNSET && format != etmq->format) { 2988 + pr_err("CS_ETM: mixed formatted and unformatted trace not supported\n"); 2989 + return -EINVAL; 2990 + } 2991 + etmq->format = format; 2992 + return 0; 2974 2993 } 2975 2994 2976 2995 /* Wasn't inside this buffer, but there were no parse errors. 1 == 'not found' */ ··· 3225 3238 * Don't create decoders for empty queues, mainly because 3226 3239 * etmq->format is unknown for empty queues. 3227 3240 */ 3241 + assert(empty == (etmq->format == UNSET)); 3228 3242 if (empty) 3229 3243 continue; 3230 3244 ··· 3245 3257 int event_header_size = sizeof(struct perf_event_header); 3246 3258 int total_size = auxtrace_info->header.size; 3247 3259 int priv_size = 0; 3248 - int num_cpu; 3260 + int num_cpu, max_cpu = 0; 3249 3261 int err = 0; 3250 3262 int aux_hw_id_found; 3251 - int i, j; 3263 + int i; 3252 3264 u64 *ptr = NULL; 3253 3265 u64 **metadata = NULL; 3254 3266 ··· 3279 3291 * required by the trace decoder to properly decode the trace due 3280 3292 * to its highly compressed nature. 3281 3293 */ 3282 - for (j = 0; j < num_cpu; j++) { 3294 + for (int j = 0; j < num_cpu; j++) { 3283 3295 if (ptr[i] == __perf_cs_etmv3_magic) { 3284 3296 metadata[j] = 3285 3297 cs_etm__create_meta_blk(ptr, &i, ··· 3303 3315 err = -ENOMEM; 3304 3316 goto err_free_metadata; 3305 3317 } 3318 + 3319 + if ((int) metadata[j][CS_ETM_CPU] > max_cpu) 3320 + max_cpu = metadata[j][CS_ETM_CPU]; 3306 3321 } 3307 3322 3308 3323 /* ··· 3335 3344 */ 3336 3345 etm->pid_fmt = cs_etm__init_pid_fmt(metadata[0]); 3337 3346 3338 - err = auxtrace_queues__init(&etm->queues); 3347 + err = auxtrace_queues__init_nr(&etm->queues, max_cpu + 1); 3339 3348 if (err) 3340 3349 goto err_free_etm; 3350 + 3351 + for (unsigned int j = 0; j < etm->queues.nr_queues; ++j) { 3352 + err = cs_etm__setup_queue(etm, &etm->queues.queue_array[j], j); 3353 + if (err) 3354 + goto err_free_queues; 3355 + } 3341 3356 3342 3357 if (session->itrace_synth_opts->set) { 3343 3358 etm->synth_opts = *session->itrace_synth_opts; ··· 3466 3469 zfree(&etm); 3467 3470 err_free_metadata: 3468 3471 /* No need to check @metadata[j], free(NULL) is supported */ 3469 - for (j = 0; j < num_cpu; j++) 3472 + for (int j = 0; j < num_cpu; j++) 3470 3473 zfree(&metadata[j]); 3471 3474 zfree(&metadata); 3472 3475 err_free_traceid_list: