* [PATCH 1/2] coresight: etm4x: Report whether the PMU counts external output 1
@ 2026-10-01 6:37 Amir Ayupov
2026-10-01 6:37 ` [PATCH 2/2] coresight: Add pmu_pulse/extout_pulse Amir Ayupov
2026-10-07 16:24 ` [PATCH 1/2] coresight: etm4x: Report whether the PMU counts external output 1 Leo Yan
0 siblings, 2 replies; 4+ messages in thread
From: Amir Ayupov @ 2026-10-01 6:37 UTC (permalink / raw)
To: James Clark, Leo Yan, Suzuki K Poulose, Mike Leach, Alexander Shishkin
Cc: Jonathan Corbet, Shuah Khan, Randy Dunlap, coresight,
linux-arm-kernel, linux-doc, linux-kernel
cscfg features match on device class only, so a feature that drives ETM
external output 1 for the PMU to count as TRCEXTOUT1 (0x4011) would load
on every ETMv4 device, including CPUs whose PMU has no such event
(Neoverse N1) or whose PMU connection is undocumented. There the pulse is
never counted, and whatever depends on it silently does not happen.
Add a capability match flag, CS_CFG_MATCH_CAP_PMU_EXTOUT1, that features
can require. The ETM sets it at probe, on its own CPU, when:
- the CPU is one whose TRM documents ETE external outputs 0-3 as PMU
events TRCEXTOUT0-3: Cortex-A520, Cortex-X925 and Neoverse N2, N3, V2
and V3;
- PMUv3p1 or later is implemented and PMCEID0_EL0 reports TRCEXTOUT1,
which also covers a hypervisor hiding the event;
- the trace unit has event 1, since event 0 is the trace unit trigger,
which the TRBE driver treats as fatal.
The PMU only reports whether the event is implemented, not what drives
it, so the CPU list keeps the check conservative. Other cores can be
added once their manuals or hardware confirm the connection.
Matching on a flag skips the feature on other ETMs rather than failing
the load, which would unregister the device from cscfg and lose its
other configurations.
cscfg_csdev_enable_active_config() also returns success when the active
configuration is not loaded on the device, so a session selecting such
a configuration would run unconfigured. Return -EINVAL instead, so the
session fails to start on that CPU. This applies to all configurations.
Show the flag in the feature's configfs 'matches' attribute.
Assisted-by: Devmate:Opus-5.5
Signed-off-by: Amir Ayupov <aaupov@fb.com>
---
.../hwtracing/coresight/coresight-config.h | 2 +
.../hwtracing/coresight/coresight-etm4x-cfg.c | 7 ++-
.../coresight/coresight-etm4x-core.c | 44 +++++++++++++++++++
drivers/hwtracing/coresight/coresight-etm4x.h | 3 ++
.../coresight/coresight-syscfg-configfs.c | 3 ++
.../hwtracing/coresight/coresight-syscfg.c | 7 +++
6 files changed, 65 insertions(+), 1 deletion(-)
diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
index 90fd937d3bd83..2efe73a0d0a0d 100644
--- a/drivers/hwtracing/coresight/coresight-config.h
+++ b/drivers/hwtracing/coresight/coresight-config.h
@@ -29,6 +29,8 @@
*/
#define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */
#define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */
+/* ETM external output 1 is countable by the PMU as TRCEXTOUT1 */
+#define CS_CFG_MATCH_CAP_PMU_EXTOUT1 0x0004
/* 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..2847d2d7f7bed 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
@@ -174,9 +174,14 @@ 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;
- return cscfg_register_csdev(csdev, CS_CFG_ETM4_MATCH_FLAGS, &ops);
+ if (drvdata->pmu_extout1)
+ match_flags |= CS_CFG_MATCH_CAP_PMU_EXTOUT1;
+
+ 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..7dc29727f07db 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,47 @@ static void etm4_fixup_wrong_ccitmin(struct etmv4_drvdata *drvdata)
}
}
+/*
+ * CPUs whose Technical Reference Manuals document ETE external outputs 0-3 as
+ * the PMU common events TRCEXTOUT0-3.
+ */
+static const struct midr_range etm4_pmu_extout1_cpus[] = {
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_A520),
+ MIDR_ALL_VERSIONS(MIDR_CORTEX_X925),
+ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
+ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N3),
+ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2),
+ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3),
+ {},
+};
+
+/*
+ * Check whether a PMU event can count external output 1 of this trace unit,
+ * and whether the trace unit has event 1 to drive it, since event 0 is the
+ * trace unit trigger. The PMU only reports whether an event is implemented,
+ * not that the trace unit drives it, so also require a CPU whose manual
+ * documents the connection.
+ *
+ * Must run on the CPU that owns the trace unit.
+ */
+static bool etm4_pmu_has_extout1(struct etmv4_drvdata *drvdata)
+{
+ int pmuver = read_pmuver();
+
+ if (!is_midr_in_range_list(etm4_pmu_extout1_cpus))
+ return false;
+
+ /* PMCEID0_EL0[63:32] describe events 0x4000-0x401f from PMUv3p1 */
+ if (!pmuv3_implemented(pmuver) || pmuver < ID_AA64DFR0_EL1_PMUVer_V3P1)
+ return false;
+ if (!(read_pmceid0() & BIT_ULL(32 + ARMV8_PMUV3_PERFCTR_TRCEXTOUT1 -
+ ARMV8_PMUV3_EXT_COMMON_EVENT_BASE)))
+ return false;
+
+ /* nr_event is TRCIDR0.NUMEVENT, the number of events minus one */
+ return drvdata->nr_event >= 1;
+}
+
static void etm4_init_arch_data(void *info)
{
u32 etmidr0;
@@ -1522,6 +1564,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_extout1 = etm4_pmu_has_extout1(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..dbdfe48e8b6c3 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -1024,6 +1024,8 @@ struct etmv4_save_state {
* @skip_power_up: Indicates if an implementation can skip powering up
* the trace unit.
* @paused: Indicates if the trace unit is paused.
+ * @pmu_extout1: The PMU counts external output 1 of this trace unit as
+ * TRCEXTOUT1, and the trace unit has event 1 to drive it.
* @arch_features: Bitmap of arch features of etmv4 devices.
*/
struct etmv4_drvdata {
@@ -1076,6 +1078,7 @@ struct etmv4_drvdata {
bool lpoverride : 1;
bool skip_power_up : 1;
bool paused : 1;
+ bool pmu_extout1 : 1;
u64 trfcr;
struct etmv4_config config;
struct etmv4_save_state *save_state;
diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
index 2b40e556be872..cd446d7ca43da 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
@@ -250,6 +250,9 @@ 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 ");
+ if (match_flags & CS_CFG_MATCH_CAP_PMU_EXTOUT1)
+ used += scnprintf(page + used, PAGE_SIZE - used, "PMU_EXTOUT1 ");
+
used += scnprintf(page + used, PAGE_SIZE - used, "\n");
return used;
}
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
index 2bfdd7b45e49c..953c060c88549 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg.c
@@ -1116,6 +1116,13 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
if (err)
cscfg_config_desc_put(config_desc);
+ } else {
+ /*
+ * The configuration is active but was not loaded on this
+ * device, for example because the device lacks a capability
+ * its features require. Fail rather than trace without it.
+ */
+ err = -EINVAL;
}
return err;
--
2.52.0
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH 2/2] coresight: Add pmu_pulse/extout_pulse
2026-10-01 6:37 [PATCH 1/2] coresight: etm4x: Report whether the PMU counts external output 1 Amir Ayupov
@ 2026-10-01 6:37 ` Amir Ayupov
2026-10-07 16:24 ` [PATCH 1/2] coresight: etm4x: Report whether the PMU counts external output 1 Leo Yan
1 sibling, 0 replies; 4+ messages in thread
From: Amir Ayupov @ 2026-10-01 6:37 UTC (permalink / raw)
To: James Clark, Leo Yan, Suzuki K Poulose, Mike Leach, Alexander Shishkin
Cc: Jonathan Corbet, Shuah Khan, Randy Dunlap, coresight,
linux-arm-kernel, linux-doc, linux-kernel
Add ETMv4 configuration 'pmu_pulse' with 'extout_pulse' feature which
requires CS_CFG_MATCH_CAP_PMU_EXTOUT1: 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..b5c0c0acbe1de 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 (Cortex-A520, Cortex-X925, Neoverse N2, N3, V2 and V3); 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..643c9a12018d8
--- /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_CAP_PMU_EXTOUT1,
+ .nr_regs = ARRAY_SIZE(extout_pulse_regs),
+ .regs_desc = extout_pulse_regs,
+};
+
+/* create a pmu_pulse configuration */
+
+static const char * const 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] 4+ messages in thread* Re: [PATCH 1/2] coresight: etm4x: Report whether the PMU counts external output 1
2026-10-01 6:37 [PATCH 1/2] coresight: etm4x: Report whether the PMU counts external output 1 Amir Ayupov
2026-10-01 6:37 ` [PATCH 2/2] coresight: Add pmu_pulse/extout_pulse Amir Ayupov
@ 2026-10-07 16:24 ` Leo Yan
2026-10-08 8:38 ` James Clark
1 sibling, 1 reply; 4+ messages in thread
From: Leo Yan @ 2026-10-07 16:24 UTC (permalink / raw)
To: Amir Ayupov
Cc: James Clark, Suzuki K Poulose, Mike Leach, Alexander Shishkin,
Jonathan Corbet, Shuah Khan, Randy Dunlap, coresight,
linux-arm-kernel, linux-doc, linux-kernel
Hi Amir,
Thanks for the patch. I have a few initial comments below. We may have
further feedback after our internal review.
On Wed, Sep 30, 2026 at 11:37:43PM -0700, Amir Ayupov wrote:
[...]
> #define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */
> #define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */
> +/* ETM external output 1 is countable by the PMU as TRCEXTOUT1 */
> +#define CS_CFG_MATCH_CAP_PMU_EXTOUT1 0x0004
Do we need to tie this capability to TRCEXTOUT1? For example, Neoverse
V2 exposes TRCEXTOUT0 through TRCEXTOUT3 as PMU events.
> /* 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..2847d2d7f7bed 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
> @@ -174,9 +174,14 @@ 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;
>
> - return cscfg_register_csdev(csdev, CS_CFG_ETM4_MATCH_FLAGS, &ops);
> + if (drvdata->pmu_extout1)
> + match_flags |= CS_CFG_MATCH_CAP_PMU_EXTOUT1;
> +
> + return cscfg_register_csdev(csdev, match_flags, &ops);
The current matching logic succeeds if a device and feature share any
flag bit. If the feature sets both CS_CFG_MATCH_CLASS_SRC_ETM4 and
CS_CFG_MATCH_CAP_PMU_EXTOUT1, it will still load on an ETM4 device that
lacks the capability.
Could we check the capability separately when loading the feature,
perhaps in cscfg_load_feat_csdev(), and skip it on unsupported devices?
> +static bool etm4_pmu_has_extout1(struct etmv4_drvdata *drvdata)
> +{
> + int pmuver = read_pmuver();
> +
> + if (!is_midr_in_range_list(etm4_pmu_extout1_cpus))
> + return false;
Based on specific CPU variant, we should already have identified
TRCEXTOUT has supported.
So either we only base on MIDR list or we can figure out a reliable
way to detect the feature dynamically.
> +
> + /* PMCEID0_EL0[63:32] describe events 0x4000-0x401f from PMUv3p1 */
> + if (!pmuv3_implemented(pmuver) || pmuver < ID_AA64DFR0_EL1_PMUVer_V3P1)
> + return false;
> + if (!(read_pmceid0() & BIT_ULL(32 + ARMV8_PMUV3_PERFCTR_TRCEXTOUT1 -
> + ARMV8_PMUV3_EXT_COMMON_EVENT_BASE)))
> + return false;
> +
> + /* nr_event is TRCIDR0.NUMEVENT, the number of events minus one */
> + return drvdata->nr_event >= 1;
> +}
[...]
> @@ -1116,6 +1116,13 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
>
> if (err)
> cscfg_config_desc_put(config_desc);
> + } else {
> + /*
> + * The configuration is active but was not loaded on this
> + * device, for example because the device lacks a capability
> + * its features require. Fail rather than trace without it.
> + */
> + err = -EINVAL;
> }
This fixes a pre-existing issue. It is worther to put it in a separate
patch with fixes tag:
An early return would also avoid the normal enable path's indentation:
if (!config_csdev_active)
return -EINVAL;
err = cscfg_csdev_enable_config(config_csdev_active, preset);
...
Thanks,
Leo
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH 1/2] coresight: etm4x: Report whether the PMU counts external output 1
2026-10-07 16:24 ` [PATCH 1/2] coresight: etm4x: Report whether the PMU counts external output 1 Leo Yan
@ 2026-10-08 8:38 ` James Clark
0 siblings, 0 replies; 4+ messages in thread
From: James Clark @ 2026-10-08 8:38 UTC (permalink / raw)
To: Leo Yan, Amir Ayupov
Cc: Suzuki K Poulose, Mike Leach, Alexander Shishkin,
Jonathan Corbet, Shuah Khan, Randy Dunlap, coresight,
linux-arm-kernel, linux-doc, linux-kernel
On 07/10/2026 17:24, Leo Yan wrote:
> Hi Amir,
>
> Thanks for the patch. I have a few initial comments below. We may have
> further feedback after our internal review.
>
> On Wed, Sep 30, 2026 at 11:37:43PM -0700, Amir Ayupov wrote:
>
> [...]
>
>> #define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */
>> #define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */
>> +/* ETM external output 1 is countable by the PMU as TRCEXTOUT1 */
>> +#define CS_CFG_MATCH_CAP_PMU_EXTOUT1 0x0004
>
> Do we need to tie this capability to TRCEXTOUT1? For example, Neoverse
> V2 exposes TRCEXTOUT0 through TRCEXTOUT3 as PMU events.
>
Shouldn't we also use TRCEXTOUT0 instead of 1? Isn't 1 for devices that
have two external outputs, but some devices might only have 1 output so
only have TRCEXTOUT0?
>> /* 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..2847d2d7f7bed 100644
>> --- a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
>> +++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
>> @@ -174,9 +174,14 @@ 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;
>>
>> - return cscfg_register_csdev(csdev, CS_CFG_ETM4_MATCH_FLAGS, &ops);
>> + if (drvdata->pmu_extout1)
>> + match_flags |= CS_CFG_MATCH_CAP_PMU_EXTOUT1;
>> +
>> + return cscfg_register_csdev(csdev, match_flags, &ops);
>
> The current matching logic succeeds if a device and feature share any
> flag bit. If the feature sets both CS_CFG_MATCH_CLASS_SRC_ETM4 and
> CS_CFG_MATCH_CAP_PMU_EXTOUT1, it will still load on an ETM4 device that
> lacks the capability.
>
> Could we check the capability separately when loading the feature,
> perhaps in cscfg_load_feat_csdev(), and skip it on unsupported devices?
>
>> +static bool etm4_pmu_has_extout1(struct etmv4_drvdata *drvdata)
>> +{
>> + int pmuver = read_pmuver();
>> +
>> + if (!is_midr_in_range_list(etm4_pmu_extout1_cpus))
>> + return false;
>
> Based on specific CPU variant, we should already have identified
> TRCEXTOUT has supported.
>
> So either we only base on MIDR list or we can figure out a reliable
> way to detect the feature dynamically.
>
At least with ETE the ARM says:
D4.6.12 External Outputs
SRBKWBThe TRCIDR0.NUMEVENT field shows how many ETEEvents are
for the particular implementation
0x4011, TRCEXTOUT1, Trace unit external output 1
D14 PMU Event Descriptions
The counter counts each event signaled by the trace unit on external
event 1.
It is IMPLEMENTATION DEFINED whether this event is available as an
external input to the ETE.
PMCEID0_EL0[49] reads as 1 if this event is implemented and 0
otherwise.
The number of outputs and the PMU event are both discoverable. It
specifically says that only the external input is implementation
defined, implying that if it's available it's always connected as an output.
We could leave the MIDR list to only support errata when the external
output isn't connected to the PMU event.
>> +
>> + /* PMCEID0_EL0[63:32] describe events 0x4000-0x401f from PMUv3p1 */
>> + if (!pmuv3_implemented(pmuver) || pmuver < ID_AA64DFR0_EL1_PMUVer_V3P1)
>> + return false;
>> + if (!(read_pmceid0() & BIT_ULL(32 + ARMV8_PMUV3_PERFCTR_TRCEXTOUT1 -
>> + ARMV8_PMUV3_EXT_COMMON_EVENT_BASE)))
>> + return false;
>> +
>> + /* nr_event is TRCIDR0.NUMEVENT, the number of events minus one */
>> + return drvdata->nr_event >= 1;
>> +}
>
> [...]
>
>> @@ -1116,6 +1116,13 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
>>
>> if (err)
>> cscfg_config_desc_put(config_desc);
>> + } else {
>> + /*
>> + * The configuration is active but was not loaded on this
>> + * device, for example because the device lacks a capability
>> + * its features require. Fail rather than trace without it.
>> + */
>> + err = -EINVAL;
>> }
>
> This fixes a pre-existing issue. It is worther to put it in a separate
> patch with fixes tag:
>
> An early return would also avoid the normal enable path's indentation:
>
> if (!config_csdev_active)
> return -EINVAL;
>
> err = cscfg_csdev_enable_config(config_csdev_active, preset);
> ...
>
> Thanks,
> Leo
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-08 8:38 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-01 6:37 [PATCH 1/2] coresight: etm4x: Report whether the PMU counts external output 1 Amir Ayupov
2026-10-01 6:37 ` [PATCH 2/2] coresight: Add pmu_pulse/extout_pulse Amir Ayupov
2026-10-07 16:24 ` [PATCH 1/2] coresight: etm4x: Report whether the PMU counts external output 1 Leo Yan
2026-10-08 8:38 ` James Clark
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®