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

coresight: Emit sink ID in the HW_ID packets

For Perf to be able to decode when per-sink trace IDs are used, emit the
sink that's being written to for each ETM.

Perf currently errors out if it sees a newer packet version so instead
of bumping it, add a new minor version field. This can be used to
signify new versions that have backwards compatible fields. Considering
this change is only for high core count machines, it doesn't make sense
to make a breaking change for everyone.

Signed-off-by: James Clark <james.clark@arm.com>
Tested-by: Leo Yan <leo.yan@arm.com>
Reviewed-by: Mike Leach <mike.leach@linaro.org>
Signed-off-by: James Clark <james.clark@linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20240722101202.26915-17-james.clark@linaro.org

authored by

James Clark and committed by
Suzuki K Poulose
487eec8d de0029fd

+39 -21
+14 -12
drivers/hwtracing/coresight/coresight-core.c
··· 487 487 return csdev; 488 488 } 489 489 490 + u32 coresight_get_sink_id(struct coresight_device *csdev) 491 + { 492 + if (!csdev->ea) 493 + return 0; 494 + 495 + /* 496 + * See function etm_perf_add_symlink_sink() to know where 497 + * this comes from. 498 + */ 499 + return (u32) (unsigned long) csdev->ea->var; 500 + } 501 + 490 502 static int coresight_sink_by_id(struct device *dev, const void *data) 491 503 { 492 504 struct coresight_device *csdev = to_coresight_device(dev); 493 - unsigned long hash; 494 505 495 506 if (csdev->type == CORESIGHT_DEV_TYPE_SINK || 496 - csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) { 497 - 498 - if (!csdev->ea) 499 - return 0; 500 - /* 501 - * See function etm_perf_add_symlink_sink() to know where 502 - * this comes from. 503 - */ 504 - hash = (unsigned long)csdev->ea->var; 505 - 506 - if ((u32)hash == *(u32 *)data) 507 + csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) { 508 + if (coresight_get_sink_id(csdev) == *(u32 *)data) 507 509 return 1; 508 510 } 509 511
+11 -5
drivers/hwtracing/coresight/coresight-etm-perf.c
··· 460 460 struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu); 461 461 struct list_head *path; 462 462 u64 hw_id; 463 + u8 trace_id; 463 464 464 465 if (!csdev) 465 466 goto fail; ··· 513 512 */ 514 513 if (!cpumask_test_cpu(cpu, &event_data->aux_hwid_done)) { 515 514 cpumask_set_cpu(cpu, &event_data->aux_hwid_done); 516 - hw_id = FIELD_PREP(CS_AUX_HW_ID_VERSION_MASK, 517 - CS_AUX_HW_ID_CURR_VERSION); 518 - hw_id |= FIELD_PREP(CS_AUX_HW_ID_TRACE_ID_MASK, 519 - coresight_trace_id_read_cpu_id_map(cpu, 520 - &sink->perf_sink_id_map)); 515 + 516 + trace_id = coresight_trace_id_read_cpu_id_map(cpu, &sink->perf_sink_id_map); 517 + 518 + hw_id = FIELD_PREP(CS_AUX_HW_ID_MAJOR_VERSION_MASK, 519 + CS_AUX_HW_ID_MAJOR_VERSION); 520 + hw_id |= FIELD_PREP(CS_AUX_HW_ID_MINOR_VERSION_MASK, 521 + CS_AUX_HW_ID_MINOR_VERSION); 522 + hw_id |= FIELD_PREP(CS_AUX_HW_ID_TRACE_ID_MASK, trace_id); 523 + hw_id |= FIELD_PREP(CS_AUX_HW_ID_SINK_ID_MASK, coresight_get_sink_id(sink)); 524 + 521 525 perf_report_aux_output_id(event, hw_id); 522 526 } 523 527
+1
drivers/hwtracing/coresight/coresight-priv.h
··· 148 148 struct coresight_device *target); 149 149 void coresight_remove_links(struct coresight_device *orig, 150 150 struct coresight_connection *conn); 151 + u32 coresight_get_sink_id(struct coresight_device *csdev); 151 152 152 153 #if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X) 153 154 extern int etm_readl_cp14(u32 off, unsigned int *val);
+13 -4
include/linux/coresight-pmu.h
··· 49 49 * Interpretation of the PERF_RECORD_AUX_OUTPUT_HW_ID payload. 50 50 * Used to associate a CPU with the CoreSight Trace ID. 51 51 * [07:00] - Trace ID - uses 8 bits to make value easy to read in file. 52 - * [59:08] - Unused (SBZ) 53 - * [63:60] - Version 52 + * [39:08] - Sink ID - as reported in /sys/bus/event_source/devices/cs_etm/sinks/ 53 + * Added in minor version 1. 54 + * [55:40] - Unused (SBZ) 55 + * [59:56] - Minor Version - previously existing fields are compatible with 56 + * all minor versions. 57 + * [63:60] - Major Version - previously existing fields mean different things 58 + * in new major versions. 54 59 */ 55 60 #define CS_AUX_HW_ID_TRACE_ID_MASK GENMASK_ULL(7, 0) 56 - #define CS_AUX_HW_ID_VERSION_MASK GENMASK_ULL(63, 60) 61 + #define CS_AUX_HW_ID_SINK_ID_MASK GENMASK_ULL(39, 8) 57 62 58 - #define CS_AUX_HW_ID_CURR_VERSION 0 63 + #define CS_AUX_HW_ID_MINOR_VERSION_MASK GENMASK_ULL(59, 56) 64 + #define CS_AUX_HW_ID_MAJOR_VERSION_MASK GENMASK_ULL(63, 60) 65 + 66 + #define CS_AUX_HW_ID_MAJOR_VERSION 0 67 + #define CS_AUX_HW_ID_MINOR_VERSION 1 59 68 60 69 #endif