]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
coresight: Extend width of timestamp format attribute
authorJames Clark <james.clark@linaro.org>
Fri, 28 Nov 2025 11:55:24 +0000 (11:55 +0000)
committerSuzuki K Poulose <suzuki.poulose@arm.com>
Mon, 22 Dec 2025 15:30:54 +0000 (15:30 +0000)
'timestamp' is currently 1 bit wide for on/off. To enable setting
different intervals, extend it to 4 bits wide. Keep the old bit position
for backward compatibility ("deprecated_timestamp") but don't publish in
the format/ folder. It will be removed from the documentation and can be
removed completely after enough time has passed.

ETM3x doesn't support different intervals, so validate that the value is
either 0 or 1.

Tools that read the bit positions from the format/ folder will continue
to work as before, setting either 0 or 1 for off/on. Tools that
incorrectly didn't do this and set the ETM_OPT_TS bit directly will also
continue to work because that old bit is still checked.

This avoids adding a second timestamp attribute for setting the
interval. This would be awkward to use because tools would have to be
updated to ensure that the timestamps are always enabled when an
interval is set, and the driver would have to validate that both options
are provided together. All this does is implement the semantics of a
single enum but spread over multiple fields.

Reviewed-by: Leo Yan <leo.yan@arm.com>
Tested-by: Leo Yan <leo.yan@arm.com>
Tested-by: Jie Gan <jie.gan@oss.qualcomm.com>
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/20251128-james-cs-syncfreq-v8-12-4d319764cc58@linaro.org
drivers/hwtracing/coresight/coresight-etm-perf.h
drivers/hwtracing/coresight/coresight-etm3x-core.c
drivers/hwtracing/coresight/coresight-etm4x-core.c

index c794087a0e992f35332437df44eecd54774763c0..24d929428633f56f24a114d5bb93b8ac4799ca11 100644 (file)
@@ -23,6 +23,9 @@ struct cscfg_config_desc;
 #define ATTR_CFG_FLD_preset_CFG                        config
 #define ATTR_CFG_FLD_preset_LO                 0
 #define ATTR_CFG_FLD_preset_HI                 3
+#define ATTR_CFG_FLD_timestamp_CFG             config
+#define ATTR_CFG_FLD_timestamp_LO              4
+#define ATTR_CFG_FLD_timestamp_HI              7
 #define ATTR_CFG_FLD_branch_broadcast_CFG      config
 #define ATTR_CFG_FLD_branch_broadcast_LO       8
 #define ATTR_CFG_FLD_branch_broadcast_HI       8
@@ -35,9 +38,13 @@ struct cscfg_config_desc;
 #define ATTR_CFG_FLD_contextid2_CFG            config
 #define ATTR_CFG_FLD_contextid2_LO             15
 #define ATTR_CFG_FLD_contextid2_HI             15
-#define ATTR_CFG_FLD_timestamp_CFG             config
-#define ATTR_CFG_FLD_timestamp_LO              28
-#define ATTR_CFG_FLD_timestamp_HI              28
+/*
+ * Old position of 'timestamp' and not published in sysfs. Remove at a later
+ * date if necessary.
+ */
+#define ATTR_CFG_FLD_deprecated_timestamp_CFG  config
+#define ATTR_CFG_FLD_deprecated_timestamp_LO   28
+#define ATTR_CFG_FLD_deprecated_timestamp_HI   28
 #define ATTR_CFG_FLD_retstack_CFG              config
 #define ATTR_CFG_FLD_retstack_LO               29
 #define ATTR_CFG_FLD_retstack_HI               29
index 584d653eda8166361bbf275b2de82149b3def27f..57e4a21c8fdd9db480437152d815df57269d2d48 100644 (file)
@@ -310,6 +310,7 @@ static int etm_parse_event_config(struct etm_drvdata *drvdata,
 {
        struct etm_config *config = &drvdata->config;
        struct perf_event_attr *attr = &event->attr;
+       u8 ts_level;
 
        if (!attr)
                return -EINVAL;
@@ -338,7 +339,16 @@ static int etm_parse_event_config(struct etm_drvdata *drvdata,
        if (ATTR_CFG_GET_FLD(attr, cycacc))
                config->ctrl |= ETMCR_CYC_ACC;
 
-       if (ATTR_CFG_GET_FLD(attr, timestamp))
+       ts_level = max(ATTR_CFG_GET_FLD(attr, timestamp),
+                      ATTR_CFG_GET_FLD(attr, deprecated_timestamp));
+
+       if (ts_level > 1) {
+               dev_dbg(&drvdata->csdev->dev,
+                       "timestamp format attribute should be 0 (off) or 1 (on)\n");
+               return -EINVAL;
+       }
+
+       if (ts_level)
                config->ctrl |= ETMCR_TIMESTAMP_EN;
 
        /*
index 7e9c923acf4bd3a6586dabb06e7a6607cb1f5db3..d565a73f0042e3e0b21fcf9cb94009cc25834d3d 100644 (file)
@@ -750,6 +750,9 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
        int ret = 0;
        struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
        struct etmv4_config *config = &drvdata->config;
+       struct perf_event_attr max_timestamp = {
+               .ATTR_CFG_FLD_timestamp_CFG = U64_MAX,
+       };
        struct perf_event_attr *attr = &event->attr;
        unsigned long cfg_hash;
        int preset, cc_threshold;
@@ -790,21 +793,23 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
                config->ccctlr = cc_threshold;
        }
 
-       ts_level = ATTR_CFG_GET_FLD(attr, timestamp);
+       ts_level = max(ATTR_CFG_GET_FLD(attr, timestamp),
+                      ATTR_CFG_GET_FLD(attr, deprecated_timestamp));
        if (ts_level) {
                /*
-                * Configure timestamps to be emitted at regular intervals in
-                * order to correlate instructions executed on different CPUs
-                * (CPU-wide trace scenarios).
+                * Don't do counter generated timestamps when ts_level == MAX.
+                * Leave only SYNC timestamps from TRCCONFIGR_TS.
                 */
-               ret = etm4_config_timestamp_event(drvdata, ts_level);
+               if (ts_level != ATTR_CFG_GET_FLD(&max_timestamp, timestamp)) {
+                       ret = etm4_config_timestamp_event(drvdata, ts_level);
 
-               /*
-                * No need to go further if timestamp intervals can't
-                * be configured.
-                */
-               if (ret)
-                       goto out;
+                       /*
+                        * Error if user asked for timestamps but there was no
+                        * free counter.
+                        */
+                       if (ret)
+                               goto out;
+               }
 
                /* bit[11], Global timestamp tracing bit */
                config->cfg |= TRCCONFIGR_TS;