* [PATCH v2 1/4] coresight: syscfg: Fail to enable a configuration not loaded on the device
2026-10-12 23:05 [PATCH v2 0/4] coresight: Pulse an ETM external output for a PMU event Amir Ayupov
@ 2026-10-12 23:05 ` Amir Ayupov
2026-10-21 14:09 ` Leo Yan
2026-10-12 23:05 ` [PATCH v2 2/4] coresight: syscfg: Match feature capabilities separately from device class Amir Ayupov
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Amir Ayupov @ 2026-10-12 23:05 UTC (permalink / raw)
To: James Clark, Leo Yan, Suzuki K Poulose, Mike Leach, Alexander Shishkin
Cc: Greg Kroah-Hartman, Jonathan Corbet, Mathieu Poirier,
Randy Dunlap, Shuah Khan, coresight, linux-arm-kernel, linux-doc,
linux-kernel
cscfg_csdev_enable_active_config() looks up the selected configuration in
the device's loaded configurations, and returns success when it is not
there. A configuration is only loaded on devices that match at least one
of its features, so a perf session or sysfs enable that selects it on any
other device runs without the configuration, with no error.
Return -EINVAL instead, so enabling the source fails on that device. The
function is only called with a non-zero configuration hash, so sources
enabled without a configuration are unaffected.
Fixes: f8cce2ff3c04 ("coresight: syscfg: Add API to activate and enable configurations")
Assisted-by: Devmate:Opus-5.5
Signed-off-by: Amir Ayupov <aaupov@fb.com>
---
.../hwtracing/coresight/coresight-syscfg.c | 53 ++++++++++---------
1 file changed, 28 insertions(+), 25 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
index 2bfdd7b45e49c..a816c22c87bc8 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg.c
@@ -1088,36 +1088,39 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
/*
- * If found, attempt to enable
+ * The configuration is active but not loaded on this device, because
+ * none of its features match the device. Fail rather than trace
+ * without it.
*/
- if (config_csdev_active) {
+ if (!config_csdev_active)
+ return -EINVAL;
+
+ /*
+ * Call the generic routine that will program up the internal
+ * driver structures prior to programming up the hardware.
+ * This routine takes the driver spinlock saved in the configs.
+ */
+ err = cscfg_csdev_enable_config(config_csdev_active, preset);
+ if (!err) {
/*
- * Call the generic routine that will program up the internal
- * driver structures prior to programming up the hardware.
- * This routine takes the driver spinlock saved in the configs.
+ * Successful programming. Check the active_cscfg_ctxt
+ * pointer to ensure no pre-emption disabled it via
+ * cscfg_csdev_disable_active_config() before
+ * we could start.
+ *
+ * Set enabled if OK, err if not.
*/
- err = cscfg_csdev_enable_config(config_csdev_active, preset);
- if (!err) {
- /*
- * Successful programming. Check the active_cscfg_ctxt
- * pointer to ensure no pre-emption disabled it via
- * cscfg_csdev_disable_active_config() before
- * we could start.
- *
- * Set enabled if OK, err if not.
- */
- raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
- if (csdev->active_cscfg_ctxt)
- config_csdev_active->enabled = true;
- else
- err = -EBUSY;
- raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
- }
-
- if (err)
- cscfg_config_desc_put(config_desc);
+ raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
+ if (csdev->active_cscfg_ctxt)
+ config_csdev_active->enabled = true;
+ else
+ err = -EBUSY;
+ raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
}
+ if (err)
+ cscfg_config_desc_put(config_desc);
+
return err;
}
EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config);
--
2.52.0
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH v2 1/4] coresight: syscfg: Fail to enable a configuration not loaded on the device
2026-10-12 23:05 ` [PATCH v2 1/4] coresight: syscfg: Fail to enable a configuration not loaded on the device Amir Ayupov
@ 2026-10-21 14:09 ` Leo Yan
0 siblings, 0 replies; 9+ messages in thread
From: Leo Yan @ 2026-10-21 14:09 UTC (permalink / raw)
To: Amir Ayupov
Cc: James Clark, Suzuki K Poulose, Mike Leach, Alexander Shishkin,
Greg Kroah-Hartman, Jonathan Corbet, Mathieu Poirier,
Randy Dunlap, Shuah Khan, coresight, linux-arm-kernel, linux-doc,
linux-kernel
On Mon, Oct 12, 2026 at 04:05:20PM -0700, Amir Ayupov wrote:
> cscfg_csdev_enable_active_config() looks up the selected configuration in
> the device's loaded configurations, and returns success when it is not
> there. A configuration is only loaded on devices that match at least one
> of its features, so a perf session or sysfs enable that selects it on any
> other device runs without the configuration, with no error.
>
> Return -EINVAL instead, so enabling the source fails on that device. The
> function is only called with a non-zero configuration hash, so sources
> enabled without a configuration are unaffected.
>
> Fixes: f8cce2ff3c04 ("coresight: syscfg: Add API to activate and enable configurations")
> Assisted-by: Devmate:Opus-5.5
> Signed-off-by: Amir Ayupov <aaupov@fb.com>
Reviewed-by: Leo Yan <leo.yan@arm.com>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 2/4] coresight: syscfg: Match feature capabilities separately from device class
2026-10-12 23:05 [PATCH v2 0/4] coresight: Pulse an ETM external output for a PMU event Amir Ayupov
2026-10-12 23:05 ` [PATCH v2 1/4] coresight: syscfg: Fail to enable a configuration not loaded on the device Amir Ayupov
@ 2026-10-12 23:05 ` Amir Ayupov
2026-10-21 14:39 ` Leo Yan
2026-10-12 23:05 ` [PATCH v2 3/4] coresight: etm4x: Report the external outputs the PMU counts Amir Ayupov
2026-10-12 23:05 ` [PATCH v2 4/4] coresight: Add pmu_pulse/extout_pulse Amir Ayupov
3 siblings, 1 reply; 9+ messages in thread
From: Amir Ayupov @ 2026-10-12 23:05 UTC (permalink / raw)
To: James Clark, Leo Yan, Suzuki K Poulose, Mike Leach, Alexander Shishkin
Cc: Jonathan Corbet, Randy Dunlap, Shuah Khan, coresight,
linux-arm-kernel, linux-doc, linux-kernel
A feature loads on a device when the two share any match flag. That works
for device classes, where a feature wants any one of them, but not for
capabilities a device may or may not have: a feature that sets a class
and a capability would still load on a device of that class without the
capability.
Reserve CS_CFG_MATCH_CAP_MASK for capability flags. A feature now loads on
a device that shares one of its other flags and has all of its
capabilities. Check this once in cscfg_load_feat_csdev(), which both the
feature and the device registration paths call. No capability flags are
defined yet, so matching is unchanged.
Assisted-by: Devmate:Opus-5.5
Signed-off-by: Amir Ayupov <aaupov@fb.com>
---
.../hwtracing/coresight/coresight-config.h | 6 ++++
.../hwtracing/coresight/coresight-syscfg.c | 35 +++++++++++++------
2 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
index 90fd937d3bd83..af6ef96b9ae01 100644
--- a/drivers/hwtracing/coresight/coresight-config.h
+++ b/drivers/hwtracing/coresight/coresight-config.h
@@ -30,6 +30,12 @@
#define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */
#define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */
+/*
+ * flags defining device capabilities a feature can require. A feature loads on
+ * a device that matches one of its classes and has all of its capabilities.
+ */
+#define CS_CFG_MATCH_CAP_MASK 0x0000ff00
+
/* flags defining device instance matching - used in config match desc data. */
#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
index a816c22c87bc8..1545d64afec01 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg.c
@@ -172,7 +172,21 @@ cscfg_alloc_csdev_feat(struct coresight_device *csdev, struct cscfg_feature_desc
}
/* load one feature into one coresight device */
+/*
+ * A feature matches a device that shares one of its class flags and has all of
+ * the capability flags it requires.
+ */
+static bool cscfg_match_feat_csdev(u32 feat_flags, u32 csdev_flags)
+{
+ u32 caps = feat_flags & CS_CFG_MATCH_CAP_MASK;
+
+ return (feat_flags & csdev_flags & ~CS_CFG_MATCH_CAP_MASK) &&
+ (csdev_flags & caps) == caps;
+}
+
+/* Load the feature into the device if it matches, otherwise skip it. */
static int cscfg_load_feat_csdev(struct coresight_device *csdev,
+ u32 match_flags,
struct cscfg_feature_desc *feat_desc,
struct cscfg_csdev_feat_ops *ops)
{
@@ -183,6 +197,9 @@ static int cscfg_load_feat_csdev(struct coresight_device *csdev,
if (!ops->load_feat)
return -EINVAL;
+ if (!cscfg_match_feat_csdev(feat_desc->match_flags, match_flags))
+ return 0;
+
feat_csdev = cscfg_alloc_csdev_feat(csdev, feat_desc);
if (!feat_csdev)
return -ENOMEM;
@@ -212,11 +229,11 @@ static int cscfg_add_feat_to_csdevs(struct cscfg_feature_desc *feat_desc)
int err;
list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) {
- if (csdev_item->match_flags & feat_desc->match_flags) {
- err = cscfg_load_feat_csdev(csdev_item->csdev, feat_desc, &csdev_item->ops);
- if (err)
- return err;
- }
+ err = cscfg_load_feat_csdev(csdev_item->csdev,
+ csdev_item->match_flags, feat_desc,
+ &csdev_item->ops);
+ if (err)
+ return err;
}
return 0;
}
@@ -739,11 +756,9 @@ static int cscfg_add_feats_csdev(struct coresight_device *csdev,
return -EINVAL;
list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) {
- if (feat_desc->match_flags & match_flags) {
- err = cscfg_load_feat_csdev(csdev, feat_desc, ops);
- if (err)
- break;
- }
+ err = cscfg_load_feat_csdev(csdev, match_flags, feat_desc, ops);
+ if (err)
+ break;
}
return err;
}
--
2.52.0
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH v2 2/4] coresight: syscfg: Match feature capabilities separately from device class
2026-10-12 23:05 ` [PATCH v2 2/4] coresight: syscfg: Match feature capabilities separately from device class Amir Ayupov
@ 2026-10-21 14:39 ` Leo Yan
0 siblings, 0 replies; 9+ messages in thread
From: Leo Yan @ 2026-10-21 14:39 UTC (permalink / raw)
To: Amir Ayupov
Cc: James Clark, Suzuki K Poulose, Mike Leach, Alexander Shishkin,
Jonathan Corbet, Randy Dunlap, Shuah Khan, coresight,
linux-arm-kernel, linux-doc, linux-kernel
On Mon, Oct 12, 2026 at 04:05:21PM -0700, Amir Ayupov wrote:
[...]
> --- a/drivers/hwtracing/coresight/coresight-config.h
> +++ b/drivers/hwtracing/coresight/coresight-config.h
> @@ -30,6 +30,12 @@
> #define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */
> #define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */
It is good to introduce a marco:
#define CS_CFG_MATCH_CLASS_MASK GENMASK_U32(7, 0)
> +/*
> + * flags defining device capabilities a feature can require. A feature loads on
> + * a device that matches one of its classes and has all of its capabilities.
> + */
> +#define CS_CFG_MATCH_CAP_MASK 0x0000ff00
To make the mask explicitly 32-bit unsigned:
#define CS_CFG_MATCH_CAP_MASK GENMASK_U32(15, 8)
> +
> /* flags defining device instance matching - used in config match desc data. */
> #define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */
Not an issue with this patch, but CS_CFG_MATCH_INST_ANY appears to be
unused and could be removed in a separate cleanup patch.
> diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
> index a816c22c87bc8..1545d64afec01 100644
> --- a/drivers/hwtracing/coresight/coresight-syscfg.c
> +++ b/drivers/hwtracing/coresight/coresight-syscfg.c
> @@ -172,7 +172,21 @@ cscfg_alloc_csdev_feat(struct coresight_device *csdev, struct cscfg_feature_desc
> }
>
> /* load one feature into one coresight device */
> +/*
> + * A feature matches a device that shares one of its class flags and has all of
> + * the capability flags it requires.
> + */
> +static bool cscfg_match_feat_csdev(u32 feat_flags, u32 csdev_flags)
> +{
> + u32 caps = feat_flags & CS_CFG_MATCH_CAP_MASK;
> +
> + return (feat_flags & csdev_flags & ~CS_CFG_MATCH_CAP_MASK) &&
> + (csdev_flags & caps) == caps;
For clearer comparison conditions:
/* Class type must be matches */
if ((feat_flags & CS_CFG_MATCH_CLASS_MASK) !=
(csdev_flags & CS_CFG_MATCH_CLASS_MASK)
return false;
/* No required capabilities miss from the device */
if (feat_flags & ~csdev_flags & CS_CFG_MATCH_CAP_MASK)
return false;
return true;
Thanks,
Leo
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 3/4] coresight: etm4x: Report the external outputs the PMU counts
2026-10-12 23:05 [PATCH v2 0/4] coresight: Pulse an ETM external output for a PMU event Amir Ayupov
2026-10-12 23:05 ` [PATCH v2 1/4] coresight: syscfg: Fail to enable a configuration not loaded on the device Amir Ayupov
2026-10-12 23:05 ` [PATCH v2 2/4] coresight: syscfg: Match feature capabilities separately from device class Amir Ayupov
@ 2026-10-12 23:05 ` Amir Ayupov
2026-10-21 16:43 ` Leo Yan
2026-10-12 23:05 ` [PATCH v2 4/4] coresight: Add pmu_pulse/extout_pulse Amir Ayupov
3 siblings, 1 reply; 9+ messages in thread
From: Amir Ayupov @ 2026-10-12 23:05 UTC (permalink / raw)
To: James Clark, Leo Yan, Suzuki K Poulose, Mike Leach, Alexander Shishkin
Cc: Jonathan Corbet, Randy Dunlap, Shuah Khan, coresight,
linux-arm-kernel, linux-doc, linux-kernel
Some CPUs count the trace unit's external outputs as the PMU common
events TRCEXTOUT0-3 (0x4010-0x4013), which lets a configuration drive a
PMU event from trace unit events. Other CPUs, Neoverse N1 for example,
have no such events, and a feature relying on them would silently do
nothing there.
Detect at probe, on the trace unit's CPU, which outputs the PMU counts:
the trace unit has an external output for each of its events
(TRCIDR0.NUMEVENT), and from PMUv3p1, PMCEID0_EL0[63:32] reports which of
the common events 0x4000-0x401f are implemented. Per the ETE
specification, an implemented TRCEXTOUTn event counts external output n;
only whether that output is also an external input is IMPLEMENTATION
DEFINED.
Add a capability match flag for each output,
CS_CFG_MATCH_CAP_PMU_EXTOUT(n), set it on ETMs whose PMU counts that
output, and show it in the feature's configfs 'matches' attribute. With
capabilities matched separately from the device class, a feature that
requires one only loads on those ETMs.
Assisted-by: Devmate:Opus-5.5
Signed-off-by: Amir Ayupov <aaupov@fb.com>
---
.../hwtracing/coresight/coresight-config.h | 4 +++
.../hwtracing/coresight/coresight-etm4x-cfg.c | 5 ++-
.../coresight/coresight-etm4x-core.c | 32 +++++++++++++++++++
drivers/hwtracing/coresight/coresight-etm4x.h | 3 ++
.../coresight/coresight-syscfg-configfs.c | 7 ++++
5 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
index af6ef96b9ae01..10e95f5ecc8d9 100644
--- a/drivers/hwtracing/coresight/coresight-config.h
+++ b/drivers/hwtracing/coresight/coresight-config.h
@@ -35,6 +35,10 @@
* a device that matches one of its classes and has all of its capabilities.
*/
#define CS_CFG_MATCH_CAP_MASK 0x0000ff00
+/* trace unit external output n is countable by the PMU as TRCEXTOUTn */
+#define CS_CFG_MATCH_CAP_PMU_EXTOUT_SHIFT 8
+#define CS_CFG_MATCH_CAP_PMU_EXTOUT_NR 4 /* TRCEXTOUT0-3 */
+#define CS_CFG_MATCH_CAP_PMU_EXTOUT(n) BIT(CS_CFG_MATCH_CAP_PMU_EXTOUT_SHIFT + (n))
/* flags defining device instance matching - used in config match desc data. */
#define CS_CFG_MATCH_INST_ANY 0x80000000 /* any instance of a class */
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
index e1a59b4345052..09a7a6b86968c 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
@@ -174,9 +174,12 @@ static int etm4_cfg_load_feature(struct coresight_device *csdev,
int etm4_cscfg_register(struct coresight_device *csdev)
{
+ struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct cscfg_csdev_feat_ops ops;
+ u32 match_flags = CS_CFG_ETM4_MATCH_FLAGS;
ops.load_feat = &etm4_cfg_load_feature;
+ match_flags |= (u32)drvdata->pmu_extout << CS_CFG_MATCH_CAP_PMU_EXTOUT_SHIFT;
- return cscfg_register_csdev(csdev, CS_CFG_ETM4_MATCH_FLAGS, &ops);
+ return cscfg_register_csdev(csdev, match_flags, &ops);
}
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 2247ad55d4442..1e78774025d13 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -30,6 +30,7 @@
#include <linux/uaccess.h>
#include <linux/perf_event.h>
#include <linux/perf/arm_pmu.h>
+#include <linux/perf/arm_pmuv3.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
@@ -1368,6 +1369,35 @@ static void etm4_fixup_wrong_ccitmin(struct etmv4_drvdata *drvdata)
}
}
+/*
+ * Find the external outputs of this trace unit that the PMU counts as the
+ * common events TRCEXTOUT0-3. The trace unit has an external output for each
+ * of its events, and PMCEID0_EL0[63:32] reports the common events
+ * 0x4000-0x401f from PMUv3p1.
+ *
+ * Must run on the CPU that owns the trace unit.
+ */
+static u8 etm4_pmu_extout(struct etmv4_drvdata *drvdata)
+{
+ int pmuver = read_pmuver();
+ u64 pmceid;
+ u8 extout = 0;
+ int n;
+
+ if (!pmuv3_implemented(pmuver) || pmuver < ID_AA64DFR0_EL1_PMUVer_V3P1)
+ return 0;
+
+ pmceid = read_pmceid0() >> 32;
+ /* nr_event is TRCIDR0.NUMEVENT, the number of events minus one */
+ for (n = 0; n <= drvdata->nr_event; n++) {
+ if (pmceid & BIT_ULL(ARMV8_PMUV3_PERFCTR_TRCEXTOUT0 + n -
+ ARMV8_PMUV3_EXT_COMMON_EVENT_BASE))
+ extout |= BIT(n);
+ }
+
+ return extout;
+}
+
static void etm4_init_arch_data(void *info)
{
u32 etmidr0;
@@ -1522,6 +1552,8 @@ static void etm4_init_arch_data(void *info)
/* NUMCNTR, bits[30:28] number of counters available for tracing */
drvdata->nr_cntr = FIELD_GET(TRCIDR5_NUMCNTR_MASK, etmidr5);
+ drvdata->pmu_extout = etm4_pmu_extout(drvdata);
+
coresight_clear_self_claim_tag_unlocked(csa);
etm4_cs_lock(drvdata, csa);
cpu_detect_trace_filtering(drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index df9e0748d71ec..11d95a4518b88 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -979,6 +979,8 @@ struct etmv4_save_state {
* @nrseqstate: The number of sequencer states that are implemented.
* @nr_seq_ctrls: The number of sequence state transition control registers.
* @nr_event: Indicates how many events the trace unit support.
+ * @pmu_extout: Bitmap of the external outputs n that the PMU counts as
+ * TRCEXTOUTn.
* @nr_resource:The number of resource selection pairs available for tracing.
* @nr_ss_cmp: Number of single-shot comparator controls that are available.
* @trcid: value of the current ID for this component.
@@ -1045,6 +1047,7 @@ struct etmv4_drvdata {
u8 nrseqstate;
u8 nr_seq_ctrls;
u8 nr_event;
+ u8 pmu_extout;
u8 nr_resource;
u8 nr_ss_cmp;
u8 trcid;
diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
index 2b40e556be872..7893d40f2e9ea 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
@@ -243,6 +243,7 @@ static ssize_t cscfg_feat_matches_show(struct config_item *item, char *page)
struct cscfg_fs_feature, group);
u32 match_flags = fs_feat->feat_desc->match_flags;
int used = 0;
+ int n;
if (match_flags & CS_CFG_MATCH_CLASS_SRC_ALL)
used = scnprintf(page, PAGE_SIZE, "SRC_ALL ");
@@ -250,6 +251,12 @@ static ssize_t cscfg_feat_matches_show(struct config_item *item, char *page)
if (match_flags & CS_CFG_MATCH_CLASS_SRC_ETM4)
used += scnprintf(page + used, PAGE_SIZE - used, "SRC_ETMV4 ");
+ for (n = 0; n < CS_CFG_MATCH_CAP_PMU_EXTOUT_NR; n++) {
+ if (match_flags & CS_CFG_MATCH_CAP_PMU_EXTOUT(n))
+ used += scnprintf(page + used, PAGE_SIZE - used,
+ "PMU_EXTOUT%d ", n);
+ }
+
used += scnprintf(page + used, PAGE_SIZE - used, "\n");
return used;
}
--
2.52.0
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH v2 3/4] coresight: etm4x: Report the external outputs the PMU counts
2026-10-12 23:05 ` [PATCH v2 3/4] coresight: etm4x: Report the external outputs the PMU counts Amir Ayupov
@ 2026-10-21 16:43 ` Leo Yan
0 siblings, 0 replies; 9+ messages in thread
From: Leo Yan @ 2026-10-21 16:43 UTC (permalink / raw)
To: Amir Ayupov
Cc: James Clark, Suzuki K Poulose, Mike Leach, Alexander Shishkin,
Jonathan Corbet, Randy Dunlap, Shuah Khan, coresight,
linux-arm-kernel, linux-doc, linux-kernel
On Mon, Oct 12, 2026 at 04:05:22PM -0700, Amir Ayupov wrote:
[...]
> --- a/drivers/hwtracing/coresight/coresight-config.h
> +++ b/drivers/hwtracing/coresight/coresight-config.h
> @@ -35,6 +35,10 @@
> * a device that matches one of its classes and has all of its capabilities.
> */
> #define CS_CFG_MATCH_CAP_MASK 0x0000ff00
> +/* trace unit external output n is countable by the PMU as TRCEXTOUTn */
> +#define CS_CFG_MATCH_CAP_PMU_EXTOUT_SHIFT 8
> +#define CS_CFG_MATCH_CAP_PMU_EXTOUT_NR 4 /* TRCEXTOUT0-3 */
> +#define CS_CFG_MATCH_CAP_PMU_EXTOUT(n) BIT(CS_CFG_MATCH_CAP_PMU_EXTOUT_SHIFT + (n))
We can just use a single capacity for all output singals. It would be
good to follow the naming convention in the Arm ARM:
#define CS_CFG_MATCH_CAP_TRCEXTOUT BIT(8)
> int etm4_cscfg_register(struct coresight_device *csdev)
> {
> + struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> struct cscfg_csdev_feat_ops ops;
> + u32 match_flags = CS_CFG_ETM4_MATCH_FLAGS;
>
> ops.load_feat = &etm4_cfg_load_feature;
> + match_flags |= (u32)drvdata->pmu_extout << CS_CFG_MATCH_CAP_PMU_EXTOUT_SHIFT;
>
> - return cscfg_register_csdev(csdev, CS_CFG_ETM4_MATCH_FLAGS, &ops);
> + return cscfg_register_csdev(csdev, match_flags, &ops);
I would suggest to enable the capability bit base on drvdata->caps:
if (etm4x_is_ete(drvdata) && drvdata->caps.nr_events)
match_flags |= CS_CFG_MATCH_CAP_TRCEXTOUT;
For now, we can enable TRCEXTOUT for ETE only, as this should be
sufficient to detect the feature safely. I'd like to leave this to
James and Mike as I got suggestions from them.
Please also rebase onto the latest CoreSight next branch [1], which
moves the capability fields into drvdata->caps. I found an issue in the
decoding of caps.nr_event; the attached patch fixes it and makes the
field hold the actual event count.
[1] https://git.kernel.org/pub/scm/linux/kernel/git/coresight/linux.git branch: next
---8<---
From 95307fa0574b1e0b3922ffa23fe98144b2688496 Mon Sep 17 00:00:00 2001
From: Leo Yan <leo.yan@arm.com>
Date: Wed, 21 Oct 2026 17:05:18 +0100
Subject: [PATCH] coresight: etm4x: Fix event count decoding
TRCIDR0.NUMEVENT normally encodes the number of events minus one.
From ETMv4.3 onwards, including ETE, a zero TRCIDR4.NUMRSPAIR instead
means that no events are implemented and NUMEVENT is zero. The sysfs
event controls currently interpret this combination as one event and
allow writes to unsupported event fields.
Decode NUMEVENT after NUMRSPAIR and store the actual number of events
in nr_event. Use the decoded resource count so that older ETM versions,
where a zero NUMRSPAIR represents one resource pair, still report at
least one event. Update both sysfs event controls to use the actual
count and clear their event fields when no events are implemented.
Also correct the instruction event enable mask for the single-event
case to use INSTEN[0]. The existing mask uses INSTEN[1], preventing
event 0 from being enabled.
This change depends on the recent driver refactoring. With no reported
failures, it is not intended for stable backporting.
Signed-off-by: Leo Yan <leo.yan@arm.com>
---
.../coresight/coresight-etm4x-core.c | 13 +++++++--
.../coresight/coresight-etm4x-sysfs.c | 29 ++++++++++---------
2 files changed, 27 insertions(+), 15 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index e21be6468e954..af017bd8a5477 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -1451,8 +1451,6 @@ static void etm4_init_arch_data(void *info)
caps->trccci = !!(etmidr0 & TRCIDR0_TRCCCI);
/* RETSTACK, bit[9] Return stack bit */
caps->retstack = !!(etmidr0 & TRCIDR0_RETSTACK);
- /* NUMEVENT, bits[11:10] Number of events field */
- caps->nr_event = FIELD_GET(TRCIDR0_NUMEVENT_MASK, etmidr0);
/* QSUPP, bits[16:15] Q element support field */
caps->q_support = FIELD_GET(TRCIDR0_QSUPP_MASK, etmidr0);
if (caps->q_support)
@@ -1519,6 +1517,17 @@ static void etm4_init_arch_data(void *info)
caps->nr_resource = FIELD_GET(TRCIDR4_NUMRSPAIR_MASK, etmidr4);
if ((drvdata->arch < ETM_ARCH_V4_3) || (caps->nr_resource > 0))
caps->nr_resource += 1;
+
+ /*
+ * NUMEVENT encodes the number of events minus one. From ETMv4.3,
+ * including ETE, NUMRSPAIR == 0 means no events are implemented.
+ * nr_resource already accounts for the pre-ETMv4.3 encoding.
+ */
+ if (caps->nr_resource)
+ caps->nr_event = FIELD_GET(TRCIDR0_NUMEVENT_MASK, etmidr0) + 1;
+ else
+ caps->nr_event = 0;
+
/*
* NUMSSCC, bits[23:20] the number of single-shot
* comparator control for tracing. Read any status regs as these
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
index db9e603f97ba8..fb38f0102290a 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -513,19 +513,22 @@ static ssize_t event_store(struct device *dev,
raw_spin_lock(&drvdata->spinlock);
switch (caps->nr_event) {
- case 0x0:
+ case 0:
+ sysfs_config->eventctrl0 = 0;
+ break;
+ case 1:
/* EVENT0, bits[7:0] */
sysfs_config->eventctrl0 = val & 0xFF;
break;
- case 0x1:
- /* EVENT1, bits[15:8] */
+ case 2:
+ /* EVENT1, bits[15:8] */
sysfs_config->eventctrl0 = val & 0xFFFF;
break;
- case 0x2:
+ case 3:
/* EVENT2, bits[23:16] */
sysfs_config->eventctrl0 = val & 0xFFFFFF;
break;
- case 0x3:
+ case 4:
/* EVENT3, bits[31:24] */
sysfs_config->eventctrl0 = val;
break;
@@ -565,22 +568,22 @@ static ssize_t event_instren_store(struct device *dev,
/* start by clearing all instruction event enable bits */
sysfs_config->eventctrl1 &= ~TRCEVENTCTL1R_INSTEN_MASK;
switch (caps->nr_event) {
- case 0x0:
- /* generate Event element for event 1 */
- sysfs_config->eventctrl1 |= val & TRCEVENTCTL1R_INSTEN_1;
+ case 1:
+ /* generate Event element for event 0 */
+ sysfs_config->eventctrl1 |= val & TRCEVENTCTL1R_INSTEN_0;
break;
- case 0x1:
- /* generate Event element for event 1 and 2 */
+ case 2:
+ /* generate Event element for events 0 and 1 */
sysfs_config->eventctrl1 |= val & (TRCEVENTCTL1R_INSTEN_0 |
TRCEVENTCTL1R_INSTEN_1);
break;
- case 0x2:
- /* generate Event element for event 1, 2 and 3 */
+ case 3:
+ /* generate Event element for events 0, 1 and 2 */
sysfs_config->eventctrl1 |= val & (TRCEVENTCTL1R_INSTEN_0 |
TRCEVENTCTL1R_INSTEN_1 |
TRCEVENTCTL1R_INSTEN_2);
break;
- case 0x3:
+ case 4:
/* generate Event element for all 4 events */
sysfs_config->eventctrl1 |= val & (TRCEVENTCTL1R_INSTEN_0 |
TRCEVENTCTL1R_INSTEN_1 |
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 4/4] coresight: Add pmu_pulse/extout_pulse
2026-10-12 23:05 [PATCH v2 0/4] coresight: Pulse an ETM external output for a PMU event Amir Ayupov
` (2 preceding siblings ...)
2026-10-12 23:05 ` [PATCH v2 3/4] coresight: etm4x: Report the external outputs the PMU counts Amir Ayupov
@ 2026-10-12 23:05 ` Amir Ayupov
2026-10-13 1:09 ` Daniel Pereira
3 siblings, 1 reply; 9+ messages in thread
From: Amir Ayupov @ 2026-10-12 23:05 UTC (permalink / raw)
To: James Clark, Leo Yan, Suzuki K Poulose, Mike Leach, Alexander Shishkin
Cc: Jonathan Corbet, Randy Dunlap, Shuah Khan, coresight,
linux-arm-kernel, linux-doc, linux-kernel
Add ETMv4 configuration 'pmu_pulse' with 'extout_pulse' feature which
requires an ETM whose PMU counts external output 1
(CS_CFG_MATCH_CAP_PMU_EXTOUT(1)): event 1 selects the always-true
resource and drives TRCEXTOUT1 PMU event which pulses on every cycle
while the trace unit is enabled.
The intended use is for CSSPGO profiling: a fixed-length ETM strobing
window that ends at a PMU event. The window is decoded into branch
stack, PMU event is carrying callchains. pmu_pulse allows specifying the
window in ETM cycles.
Assisted-by: Devmate:Opus-5.5
Signed-off-by: Amir Ayupov <aaupov@fb.com>
---
.../trace/coresight/coresight-config.rst | 5 ++
.../trace/coresight/coresight-perf.rst | 19 +++++++
drivers/hwtracing/coresight/Makefile | 1 +
.../coresight/coresight-cfg-pmu-pulse.c | 55 +++++++++++++++++++
.../coresight/coresight-cfg-preload.c | 2 +
.../coresight/coresight-cfg-preload.h | 2 +
6 files changed, 84 insertions(+)
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-pmu-pulse.c
diff --git a/Documentation/trace/coresight/coresight-config.rst b/Documentation/trace/coresight/coresight-config.rst
index 6d5ffa6f73471..3eed728bf0de1 100644
--- a/Documentation/trace/coresight/coresight-config.rst
+++ b/Documentation/trace/coresight/coresight-config.rst
@@ -129,6 +129,11 @@ The following steps take place in the operation of a configuration.
5) At the end of the perf session, the configuration will be disabled.
+The built-in 'pmu_pulse' configuration pulses ETM external output 1 for a PMU
+event to count. It only pulses while the ETM is enabled, so combined with AUX
+pause and resume the PMU event can time each trace window (see
+coresight-perf.rst).
+
Viewing Configurations and Features
===================================
diff --git a/Documentation/trace/coresight/coresight-perf.rst b/Documentation/trace/coresight/coresight-perf.rst
index 0a77741a431ef..7163d206f9b36 100644
--- a/Documentation/trace/coresight/coresight-perf.rst
+++ b/Documentation/trace/coresight/coresight-perf.rst
@@ -109,6 +109,25 @@ Example for triggering AUX pause and resume with PMU event::
-e cycles/aux-action=pause,period=10000000/ \
-e cycles/aux-action=resume,period=1050000/ -- sleep 1
+ETM-timed pause events
+~~~~~~~~~~~~~~~~~~~~~~
+
+The built-in ``pmu_pulse`` configuration pulses ETM external output 1 on every
+cycle of allowed trace, and a PMU event counting that output pauses trace after
+``N`` pulses, here 1000 cycles::
+
+ perf record -T \
+ -e cs_etm/pmu_pulse,aux-action=start-paused,timestamp/u \
+ -e armv8_pmuv3_0/cpu_cycles,aux-action=resume,period=1050031/u \
+ -e armv8_pmuv3_0/trcextout1,aux-action=pause,period=1000,call-graph=fp/u \
+ -- ./workload
+
+Each window is about ``N`` traced cycles plus the pause interrupt latency, so
+windows are never empty and a callchain on the pause event is taken where
+trace ends. The configuration only loads where the PMU counts ETM external
+output 1, which the feature's configfs 'matches' attribute shows as
+PMU_EXTOUT1; elsewhere a session selecting it fails to start.
+
Perf test - Verify kernel and userspace perf CoreSight work
-----------------------------------------------------------
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index ab16d06783a57..568e797ac5a17 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_CORESIGHT) += coresight.o
coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \
coresight-sysfs.o coresight-syscfg.o coresight-config.o \
coresight-cfg-preload.o coresight-cfg-afdo.o coresight-cfg-pstop.o \
+ coresight-cfg-pmu-pulse.o \
coresight-syscfg-configfs.o coresight-trace-id.o
obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
coresight-tmc-y := coresight-tmc-core.o coresight-tmc-etf.o \
diff --git a/drivers/hwtracing/coresight/coresight-cfg-pmu-pulse.c b/drivers/hwtracing/coresight/coresight-cfg-pmu-pulse.c
new file mode 100644
index 0000000000000..3772e5bd6cccf
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-cfg-pmu-pulse.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pulse ETM external output 1 on every traced cycle for a PMU event to count.
+ * Based on coresight-cfg-afdo.c
+ */
+
+#include "coresight-config.h"
+
+/* ETMv4 includes and features */
+#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X)
+#include "coresight-etm4x-cfg.h"
+
+/*
+ * extout_pulse feature: event 1 selects the always-true resource, so ETM
+ * external output 1 pulses on every cycle while the trace unit is enabled. A
+ * PMU event counting that output (TRCEXTOUT1), for example with
+ * aux-action=pause, then fires after as many traced cycles as its sample
+ * period. Event 0 is avoided because it is the trace unit trigger, and the
+ * TRBE driver treats a detected trigger as fatal.
+ */
+static struct cscfg_regval_desc extout_pulse_regs[] = {
+ /* event 1: resource selector 1 (always true), drives external output 1 */
+ {
+ .type = CS_CFG_REG_TYPE_STD | CS_CFG_REG_TYPE_VAL_MASK,
+ .offset = TRCEVENTCTL0R,
+ .val32 = 0x0100,
+ .mask32 = 0xff00,
+ },
+ /* end of regs */
+};
+
+struct cscfg_feature_desc extout_pulse_etm4x = {
+ .name = "extout_pulse",
+ .description = "Pulse external output 1 on every traced cycle.\n",
+ .match_flags = CS_CFG_MATCH_CLASS_SRC_ETM4 | CS_CFG_MATCH_CAP_PMU_EXTOUT(1),
+ .nr_regs = ARRAY_SIZE(extout_pulse_regs),
+ .regs_desc = extout_pulse_regs,
+};
+
+/* create a pmu_pulse configuration */
+
+static const char *pmu_pulse_ref_names[] = {
+ "extout_pulse",
+};
+
+struct cscfg_config_desc pmu_pulse_etm4x = {
+ .name = "pmu_pulse",
+ .description = "Pulse ETM external output 1 on every traced cycle for the PMU\n"
+ "to count as TRCEXTOUT1\n",
+ .nr_feat_refs = ARRAY_SIZE(pmu_pulse_ref_names),
+ .feat_ref_names = pmu_pulse_ref_names,
+};
+
+/* end of ETM4x configurations */
+#endif /* IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X) */
diff --git a/drivers/hwtracing/coresight/coresight-cfg-preload.c b/drivers/hwtracing/coresight/coresight-cfg-preload.c
index 4980e68483c5b..a9a60a1c40845 100644
--- a/drivers/hwtracing/coresight/coresight-cfg-preload.c
+++ b/drivers/hwtracing/coresight/coresight-cfg-preload.c
@@ -14,6 +14,7 @@ static struct cscfg_feature_desc *preload_feats[] = {
#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X)
&strobe_etm4x,
&gen_etrig_etm4x,
+ &extout_pulse_etm4x,
#endif
NULL
};
@@ -22,6 +23,7 @@ static struct cscfg_config_desc *preload_cfgs[] = {
#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X)
&afdo_etm4x,
&pstop_etm4x,
+ &pmu_pulse_etm4x,
#endif
NULL
};
diff --git a/drivers/hwtracing/coresight/coresight-cfg-preload.h b/drivers/hwtracing/coresight/coresight-cfg-preload.h
index 291ba530a6a52..0058627f65ae5 100644
--- a/drivers/hwtracing/coresight/coresight-cfg-preload.h
+++ b/drivers/hwtracing/coresight/coresight-cfg-preload.h
@@ -12,4 +12,6 @@ extern struct cscfg_feature_desc strobe_etm4x;
extern struct cscfg_config_desc afdo_etm4x;
extern struct cscfg_feature_desc gen_etrig_etm4x;
extern struct cscfg_config_desc pstop_etm4x;
+extern struct cscfg_feature_desc extout_pulse_etm4x;
+extern struct cscfg_config_desc pmu_pulse_etm4x;
#endif
--
2.52.0
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH v2 4/4] coresight: Add pmu_pulse/extout_pulse
2026-10-12 23:05 ` [PATCH v2 4/4] coresight: Add pmu_pulse/extout_pulse Amir Ayupov
@ 2026-10-13 1:09 ` Daniel Pereira
0 siblings, 0 replies; 9+ messages in thread
From: Daniel Pereira @ 2026-10-13 1:09 UTC (permalink / raw)
To: Amir Ayupov
Cc: James Clark, Leo Yan, Suzuki K Poulose, Mike Leach,
Alexander Shishkin, Jonathan Corbet, Randy Dunlap, Shuah Khan,
coresight, linux-arm-kernel, linux-doc, linux-kernel
On Mon, Oct 12, 2026 at 04:05:23PM -0700, Amir Ayupov wrote:
[...]
> + perf record -T \
> + -e cs_etm/pmu_pulse,aux-action=start-paused,timestamp/u \
> + -e armv8_pmuv3_0/cpu_cycles,aux-action=resume,period=1050031/u \
> + -e armv8_pmuv3_0/trcextout1,aux-action=pause,period=1000,call-graph=fp/u \
> + -- ./workload
The CPU PMU name depends on the system: armv8_pmuv3_0 is what ACPI
systems get, while on devicetree systems it comes from the compatible
string, e.g. armv8_pmuv3 or armv8_cortex_a76. Maybe add a sentence
after the example, along the lines of:
The CPU PMU name depends on the system; the available PMUs are
listed under /sys/bus/event_source/devices/.
I applied the documentation hunks and built htmldocs, no new warnings.
With or without the above, for the documentation part:
Reviewed-by: Daniel Pereira <danielmaraboo@gmail.com>
Thanks,
Daniel
^ permalink raw reply [flat|nested] 9+ messages in thread