The current TRBE driver operates only in fill mode, where tracing stops
at the top of buffer and a maintenance interrupt is raised. Due to
interrupt latency, tracing is halted while the program continues to run,
resulting in trace data lose.
This series enhances the driver for the trigger mode to mitigate trace
discontinuity. The circle buffer mode is introduced to avoid any
maintenance interrupts during the snapshot session.
It can be divided into three parts for easier review:
Patches 01~05: Minor refactoring for disabling operations and
clearing status.
Patches 06~12: Refactor fault action and trace size calculation.
Patches 13~19: Support trigger and circle modes. To better utilize the
new buffer modes, perf sets the watermark to
one-quarter of the buffer size.
This series is applied on coresight-next branch and has been validated
on Orion O6 board:
1) The trigger count and wrap mode are verified using Ftrace logs.
2) A new kunit test module verifies limit and count calculations.
3) Basic perf record / script commands and module load/unload have
been tested successfully.
Signed-off-by: Leo Yan <leo.yan(a)arm.com>
---
Leo Yan (19):
coresight: trbe: Use helpers for checking errata
coresight: trbe: Remove redundant disable operation
coresight: trbe: Remove buffer disabling in trbe_handle_overflow()
coresight: trbe: Remove set_trbe_disabled() from the enable flow
coresight: trbe: Refactor status clearing
coresight: trbe: Refactor syndrome decoding
coresight: trbe: Refactor AUX flag setting
coresight: trbe: Use PERF_AUX_FLAG_PARTIAL instead of PERF_AUX_FLAG_COLLISION
coresight: trbe: Add fault action argument to trbe_handle_overflow()
coresight: trbe: Always check fault action when updating buffer
coresight: trbe: Apply overwrite erratum for only wrap event
coresight: trbe: Calculate size for buffer wrapping
coresight: trbe: Remove misleading comment
coresight: trbe: Refactor compute_trbe_buffer_limit()
coresight: trbe: Add static key for bypassing trigger mode
coresight: trbe: Support trigger mode
coresight: trbe: Enable circle mode for snapshot
coresight: trbe: Add kunit tests
perf: cs-etm: Set watermark for AUX trace
drivers/hwtracing/coresight/Kconfig | 9 +
drivers/hwtracing/coresight/Makefile | 1 +
.../coresight/coresight-trbe-kunit-tests.c | 536 +++++++++++++++++++++
drivers/hwtracing/coresight/coresight-trbe.c | 440 +++++++++--------
drivers/hwtracing/coresight/coresight-trbe.h | 111 ++++-
tools/perf/arch/arm/util/cs-etm.c | 7 +
6 files changed, 896 insertions(+), 208 deletions(-)
---
base-commit: 9e9182cab5ebc3ee7544e60ef08ba19fdf216920
change-id: 20251120-trbe_buffer_refactor_v1-1-8f8023105469
Best regards,
--
Leo Yan <leo.yan(a)arm.com>
On 15/12/2025 04:27, Ma Ke wrote:
> In etm_setup_aux(), when a user sink is obtained via
> coresight_get_sink_by_id(), it increments the reference count of the
> sink device. However, if the sink is used in path building, the path
> holds a reference, but the initial reference from
> coresight_get_sink_by_id() is not released, causing a reference count
> leak. We should release the initial reference after the path is built.
>
> Found by code review.
>
> Cc: stable(a)vger.kernel.org
> Fixes: 0e6c20517596 ("coresight: etm-perf: Allow an event to use different sinks")
> Signed-off-by: Ma Ke <make24(a)iscas.ac.cn>
> ---
> Changes in v2:
> - modified the patch as suggestions.
I think Leo's comment on the previous v2 is still unaddressed. But
releasing it in coresight_get_sink_by_id() would make it consistent with
coresight_find_csdev_by_fwnode() and prevent further mistakes.
It also leads me to see that users of coresight_find_device_by_fwnode()
should also release it, but only one out of two appears to.
James
> ---
> drivers/hwtracing/coresight/coresight-etm-perf.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
> index 17afa0f4cdee..56d012ab6d3a 100644
> --- a/drivers/hwtracing/coresight/coresight-etm-perf.c
> +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
> @@ -454,6 +454,11 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
> goto err;
>
> out:
> + if (user_sink) {
> + put_device(&user_sink->dev);
> + user_sink = NULL;
> + }
> +
> return event_data;
>
> err:
The specific config field that an event format attribute is in is
consistently hard coded, even though the API is supposed to be that the
driver publishes the config field name. To stop this pattern from being
copy pasted and causing problems in the future, replace them all with
calls to a new helper that returns the value that a user set.
This reveals some issues in evsel__set_config_if_unset(). It doesn't
work with sparse bitfields, which are an unused but documented feature.
And it also only writes to the attr.config field. To fix it we need to
start tracking user changes for all config fields and then use existing
helper functions that support sparse bitfields. Some other refactoring
was also required and a test was added.
Signed-off-by: James Clark <james.clark(a)linaro.org>
---
Changes in v3:
- Fix uninitialized variable warning on GCC
- Fix leak of evlist in test
- Confirm no type punning issues with ubsan (Ian)
- Link to v2: https://lore.kernel.org/r/20251208-james-perf-config-bits-v2-0-4ac0281993b0…
Changes in v2:
- Remove macros in get_config_chgs() and some other refactoring.
- Support sparse bitfields in evsel__set_config_if_unset().
- Always track user changes instead of only when
'pmu->perf_event_attr_init_default' is set.
- Add a test.
- Don't bail out in cs-etm.c if any format fields are missing (Leo).
- Rename 'guess' to 'synth' (Mike).
- Link to v1: https://lore.kernel.org/r/20251201-james-perf-config-bits-v1-0-22ecbbf8007c…
---
James Clark (12):
perf parse-events: Refactor get_config_terms() to remove macros
perf evsel: Support sparse fields in evsel__set_config_if_unset()
perf parse-events: Track all user changed config bits
perf evsel: apply evsel__set_config_if_unset() to all config fields
perf evsel: Add a helper to get the value of a config field
perf parse-events: Always track user config changes
perf tests: Test evsel__set_config_if_unset() and config change tracking
perf cs-etm: Make a helper to find the Coresight evsel
perf cs-etm: Don't use hard coded config bits when setting up ETMCR
perf cs-etm: Don't use hard coded config bits when setting up TRCCONFIGR
perf cs-etm: Don't hard code config attribute when configuring the event
perf arm-spe: Don't hard code config attribute
tools/perf/arch/arm/util/cs-etm.c | 193 +++++++++++++++------------
tools/perf/arch/arm64/util/arm-spe.c | 15 ++-
tools/perf/tests/pmu.c | 91 +++++++++++++
tools/perf/util/evsel.c | 6 +-
tools/perf/util/evsel.h | 2 +
tools/perf/util/evsel_config.h | 7 +-
tools/perf/util/parse-events.c | 248 ++++++++++++++++++++---------------
tools/perf/util/pmu.c | 112 ++++++++++++++--
8 files changed, 460 insertions(+), 214 deletions(-)
---
base-commit: 2eeb09fe1c5173b659929f92fee4461796ca8c14
change-id: 20251112-james-perf-config-bits-bee7106f0f00
Best regards,
--
James Clark <james.clark(a)linaro.org>
On Tue, Dec 09, 2025 at 08:51:38PM +0800, Yingchao Deng (Consultant) wrote:
[...]
> > void cti_write_single_reg(struct cti_drvdata *drvdata,
> > int offset, u32 value)
> > {
> > CS_UNLOCK(drvdata->base);
> > writel_relaxed(value, cti_reg_addr(drvdata, offset));
> > CS_LOCK(drvdata->base);
> > }
>
> However, since we also need to handle cti_reg_addr_with_nr, it will be
> necessary to add an additional parameter "nr" to cti_write_single_reg?
I expect the argument "offset" has already containted the nr in
bits[31..28], so don't need to pass "nr" parameter to
cti_write_single_reg().
You will change inen_store() / outen_store(), e.g.,:
cti_write_single_reg(drvdata, CTI_REG_SET_NR(CTIINEN, index),
value);
Just remind, this might be a separate refactor for common code and you
need to write a patch for this, then is followed by QCOM CTI support
patch.
Thanks,
Leo
The specific config field that an event format attribute is in is
consistently hard coded, even though the API is supposed to be that the
driver publishes the config field name. To stop this pattern from being
copy pasted and causing problems in the future, replace them all with
calls to a new helper that returns the value that a user set.
This reveals some issues in evsel__set_config_if_unset(). It doesn't
work with sparse bitfields, which are an unused but documented feature.
And it also only writes to the attr.config field. To fix it we need to
start tracking user changes for all config fields and then use existing
helper functions that support sparse bitfields. Some other refactoring
was also required and a test was added.
Signed-off-by: James Clark <james.clark(a)linaro.org>
---
Changes in v2:
- Remove macros in get_config_chgs() and some other refactoring.
- Support sparse bitfields in evsel__set_config_if_unset().
- Always track user changes instead of only when
'pmu->perf_event_attr_init_default' is set.
- Add a test.
- Don't bail out in cs-etm.c if any format fields are missing (Leo).
- Rename 'guess' to 'synth' (Mike).
- Link to v1: https://lore.kernel.org/r/20251201-james-perf-config-bits-v1-0-22ecbbf8007c…
---
James Clark (12):
perf parse-events: Refactor get_config_terms() to remove macros
perf evsel: Support sparse fields in evsel__set_config_if_unset()
perf parse-events: Track all user changed config bits
perf evsel: apply evsel__set_config_if_unset() to all config fields
perf evsel: Add a helper to get the value of a config field
perf parse-events: Always track user config changes
perf tests: Test evsel__set_config_if_unset() and config change tracking
perf cs-etm: Make a helper to find the Coresight evsel
perf cs-etm: Don't use hard coded config bits when setting up ETMCR
perf cs-etm: Don't use hard coded config bits when setting up TRCCONFIGR
perf cs-etm: Don't hard code config attribute when configuring the event
perf arm-spe: Don't hard code config attribute
tools/perf/arch/arm/util/cs-etm.c | 193 +++++++++++++++------------
tools/perf/arch/arm64/util/arm-spe.c | 15 ++-
tools/perf/tests/pmu.c | 90 +++++++++++++
tools/perf/util/evsel.c | 6 +-
tools/perf/util/evsel.h | 2 +
tools/perf/util/evsel_config.h | 7 +-
tools/perf/util/parse-events.c | 248 ++++++++++++++++++++---------------
tools/perf/util/pmu.c | 112 ++++++++++++++--
8 files changed, 459 insertions(+), 214 deletions(-)
---
base-commit: 2eeb09fe1c5173b659929f92fee4461796ca8c14
change-id: 20251112-james-perf-config-bits-bee7106f0f00
Best regards,
--
James Clark <james.clark(a)linaro.org>
Hi Yingchao,
On Tue, Dec 09, 2025 at 04:16:28PM +0800, Yingchao Deng wrote:
> Hi Leo & Mike
>
> Based on Leo’s suggestions, I created a new patch, but there are three points that do not fully align with his recommendations:
>
> 1. The helper function for returning the register address now returns only the offset, because returning the full address would conflict with cti_write_single_reg.
No need to change each callsite for cti_write_single_reg(). You could
update cti_write_single_reg() instead:
void cti_write_single_reg(struct cti_drvdata *drvdata,
int offset, u32 value)
{
CS_UNLOCK(drvdata->base);
writel_relaxed(value, cti_reg_addr(drvdata, offset));
CS_LOCK(drvdata->base);
}
> 2. For registers such as triginstatus1...3, I defined additional macros CTITRIGINSTATUS1...3. This is because CTITRIGINSTATUS + 0x4 equals CTITRIGOUTSTATUS, and to avoid conflicts with existing macros, I chose numbers starting from 0x1000 for the new definitions.
To avoid the register naming pollution, please don't define the common
names but only used for Qcom registers.
AFAIK, you even don't need to define these registers. These registers
are only used for sysfs knobs, we can define an extra "nr" field (e.g.,
bits[31..28] for indexing these registers, something like:
#define CIT_REG_NR_SHIFT 28
#define CIT_REG_NR_MASK GENMASK(31, 28)
#define CTI_REG_GET_NR(reg) FIELD_GET(CIT_REG_NR_MASK, (reg))
#define CTI_REG_SET_NR(reg, nr) ((reg) | FIELD_PREP(CIT_REG_NR_MASK, (nr))
static struct attribute *coresight_cti_regs_attrs[] = {
...
coresight_cti_reg(triginstatus, CTITRIGINSTATUS),
coresight_cti_reg(triginstatus1, CTI_REG_SET_NR(CTITRIGINSTATUS, 1)),
coresight_cti_reg(triginstatus2, CTI_REG_SET_NR(CTITRIGINSTATUS, 2)),
coresight_cti_reg(triginstatus3, CTI_REG_SET_NR(CTITRIGINSTATUS, 3)),
...
Then, you just need to decode "nr" fields in cti_qcom_reg_off().
> 3. Regarding the visibility of attributes for triginstatus1...3, since coresight_cti_reg produces an anonymous variable that cannot be directly referenced, I used coresight_cti_regs_attrs[i] to obtain the attribute corresponding to triginstatus1.
Okay, I get the meaning for "an anonymous variable" - there have no
field naming when define attr with the macro coresight_cti_reg().
but you could comparing the attr string?
if (!strcmp(attr->name, "triginstatus1") ||
!strcmp(attr->name, "triginstatus2") ||
!strcmp(attr->name, "triginstatus3"))
...
Thanks,
Leo