This reverts commit 18049c8cff9cc89daadc4df6975f7d9069638926.
The original commit claimed that contiguous AUX pages unnecessarily
exacerbate fragmentation for SPE, TRBE and ETR. This is not generally
valid: larger allocations can keep pages with the same lifetime
together, while order-0 allocations can scatter them across large
blocks and prevent free pages from coalescing [1]. The follow-up
discussion [2] has not established how forcing order-0 allocations
addresses the reported problem.
TRBE and SPE write to virtually addressed buffers. The TRBE L1 TLB
has one entry on Neoverse V2 [3] and two on Neoverse V3 [4]. Small
mappings increase translation pressure, and TTW stalls can contribute
to FIFO overflow and trace loss on TRBE.
Larger allocations provide contiguous, aligned chunks for PMD or
contiguous-PTE mappings with the proposed vmap() support [5].
With the proposed vmap() support already applied, the tests in [2]
showed that preferring larger AUX allocations reduced L2 data TLB
refills by 99.68% in the TRBE test and 34.74% in the SPE test.
Restore the previous policy of trying higher-order allocations first.
The allocator already uses __GFP_NORETRY and falls back to smaller
orders, including order 0, when larger allocations fail.
Remove PERF_PMU_CAP_AUX_PREFER_LARGE, since the restored default
provides that preference. Intel PT retains its existing allocation
behaviour, with no functional change.
[1] https://lore.kernel.org/all/aPjrRkjiIt6HmXmT@casper.infradead.org/
[2] https://lore.kernel.org/linux-arm-kernel/20260810-perf_aux_trace_large_gran…
[3] https://documentation-service.arm.com/static/633fe1ec4c59b30b517730b8#page=…
[4] https://documentation-service.arm.com/static/67361bd2c7fc0d1f211da382#page=…
[5] https://lore.kernel.org/linux-mm/20260715120813.3609949-1-jiangwen6@xiaomi.…
Signed-off-by: Leo Yan <leo.yan(a)arm.com>
---
arch/x86/events/intel/pt.c | 2 --
include/linux/perf_event.h | 5 ++---
kernel/events/ring_buffer.c | 29 +++++++++--------------------
3 files changed, 11 insertions(+), 25 deletions(-)
diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
index 49349afee6119fb6fad815c847cb3cd9daa97604..3782af40f0832a874a7f0b60961d6652513de241 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
@@ -1896,8 +1896,6 @@ static __init int pt_init(void)
if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries))
pt_pmu.pmu.capabilities = PERF_PMU_CAP_AUX_NO_SG;
- else
- pt_pmu.pmu.capabilities = PERF_PMU_CAP_AUX_PREFER_LARGE;
pt_pmu.pmu.capabilities |= PERF_PMU_CAP_EXCLUSIVE |
PERF_PMU_CAP_ITRACE |
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index eb3f7bab498ca9bee9ce7193744943b24ab2e0c5..b8d8b005f5c8a7c1def7cad02230bf9ffb876bd6 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -304,9 +304,8 @@ struct perf_event_pmu_context;
#define PERF_PMU_CAP_AUX_OUTPUT 0x0080
#define PERF_PMU_CAP_EXTENDED_HW_TYPE 0x0100
#define PERF_PMU_CAP_AUX_PAUSE 0x0200
-#define PERF_PMU_CAP_AUX_PREFER_LARGE 0x0400
-#define PERF_PMU_CAP_MEDIATED_VPMU 0x0800
-#define PERF_PMU_CAP_SIMD_REGS 0x1000
+#define PERF_PMU_CAP_MEDIATED_VPMU 0x0400
+#define PERF_PMU_CAP_SIMD_REGS 0x0800
/**
* pmu::scope
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 64d4dbdc6c071b72b670dd044616f52981206ae8..95f4fbdfd2764de5b72d901d778c46302f525fad 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -684,15 +684,7 @@ int rb_alloc_aux(struct perf_buffer *rb, struct perf_event *event,
{
bool overwrite = !(flags & RING_BUFFER_WRITABLE);
int node = (event->cpu == -1) ? -1 : cpu_to_node(event->cpu);
- bool use_contiguous_pages = event->pmu->capabilities & (
- PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_AUX_PREFER_LARGE);
- /*
- * Initialize max_order to 0 for page allocation. This allocates single
- * pages to minimize memory fragmentation. This is overridden if the
- * PMU needs or prefers contiguous pages (use_contiguous_pages = true).
- */
- int max_order = 0;
- int ret = -ENOMEM;
+ int ret = -ENOMEM, max_order;
if (!has_aux(event))
return -EOPNOTSUPP;
@@ -702,8 +694,8 @@ int rb_alloc_aux(struct perf_buffer *rb, struct perf_event *event,
if (!overwrite) {
/*
- * Watermark defaults to half the buffer, to aid PMU drivers
- * in double buffering.
+ * Watermark defaults to half the buffer, and so does the
+ * max_order, to aid PMU drivers in double buffering.
*/
if (!watermark)
watermark = min_t(unsigned long,
@@ -711,19 +703,16 @@ int rb_alloc_aux(struct perf_buffer *rb, struct perf_event *event,
(unsigned long)nr_pages << (PAGE_SHIFT - 1));
/*
- * If using contiguous pages, use aux_watermark as the basis
- * for chunking to help PMU drivers honor the watermark.
+ * Use aux_watermark as the basis for chunking to
+ * help PMU drivers honor the watermark.
*/
- if (use_contiguous_pages)
- max_order = get_order(watermark);
+ max_order = get_order(watermark);
} else {
/*
- * If using contiguous pages, we need to start with the
- * max_order that fits in nr_pages, not the other way around,
- * hence ilog2() and not get_order.
+ * We need to start with the max_order that fits in nr_pages,
+ * not the other way around, hence ilog2() and not get_order.
*/
- if (use_contiguous_pages)
- max_order = ilog2(nr_pages);
+ max_order = ilog2(nr_pages);
watermark = 0;
}
---
base-commit: 21a7f44fd0765fcc5194130b28767786eba1d1e7
change-id: 20261025-perf_revert_prefer_large_alloc-a0177d6379f6
Best regards,
--
Leo Yan <leo.yan(a)arm.com>
On 26/10/2026 05:48, Amir Ayupov wrote:
> CS_CFG_MATCH_INST_ANY has been defined since the system configuration was
> introduced but is not used by any configuration, feature or device.
> Remove it.
>
> Suggested-by: Leo Yan <leo.yan(a)arm.com>
> Assisted-by: Devmate:Opus-5.5
> Signed-off-by: Amir Ayupov <aaupov(a)fb.com>
> ---
> drivers/hwtracing/coresight/coresight-config.h | 3 ---
> 1 file changed, 3 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
> index f04e73b91d9a6..220bc54f8e5e1 100644
> --- a/drivers/hwtracing/coresight/coresight-config.h
> +++ b/drivers/hwtracing/coresight/coresight-config.h
> @@ -39,9 +39,6 @@
> */
> #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 */
> -
> /*
> * Limit number of presets in a configuration
> * This is related to the number of bits (4) we use to select the preset on
Reviewed-by: James Clark <james.clark(a)linaro.org>
On 26/10/2026 05:48, Amir Ayupov wrote:
> 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.
>
> Split the match flags into CS_CFG_MATCH_CLASS_MASK for device classes and
> CS_CFG_MATCH_CAP_MASK for capabilities. A feature now loads on a device
> that shares one of its classes 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(a)fb.com>
> ---
> .../hwtracing/coresight/coresight-config.h | 8 ++++
> .../hwtracing/coresight/coresight-syscfg.c | 37 +++++++++++++------
> 2 files changed, 34 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
> index ae6295e308131..f04e73b91d9a6 100644
> --- a/drivers/hwtracing/coresight/coresight-config.h
> +++ b/drivers/hwtracing/coresight/coresight-config.h
> @@ -7,6 +7,7 @@
> #ifndef _CORESIGHT_CORESIGHT_CONFIG_H
> #define _CORESIGHT_CORESIGHT_CONFIG_H
>
> +#include <linux/bits.h>
> #include <linux/cleanup.h>
> #include <linux/coresight.h>
> #include <linux/types.h>
> @@ -30,6 +31,13 @@
> */
> #define CS_CFG_MATCH_CLASS_SRC_ALL 0x0001 /* match any source */
> #define CS_CFG_MATCH_CLASS_SRC_ETM4 0x0002 /* match any ETMv4 device */
> +#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 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 */
> diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
> index a816c22c87bc8..3ee104e94a4cd 100644
> --- a/drivers/hwtracing/coresight/coresight-syscfg.c
> +++ b/drivers/hwtracing/coresight/coresight-syscfg.c
> @@ -171,8 +171,22 @@ cscfg_alloc_csdev_feat(struct coresight_device *csdev, struct cscfg_feature_desc
> return feat_csdev;
> }
>
> -/* load one feature into one coresight device */
> +static bool cscfg_match_feat_csdev(u32 feat_flags, u32 csdev_flags)
> +{
> + /* The device must be in one of the feature's classes */
> + if (!(feat_flags & csdev_flags & CS_CFG_MATCH_CLASS_MASK))
> + return false;
> +
> + /* The device must have every capability the feature requires */
> + if (feat_flags & ~csdev_flags & CS_CFG_MATCH_CAP_MASK)
> + return false;
> +
> + return true;
> +}
> +
> +/* 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;
> }
Reviewed-by: James Clark <james.clark(a)linaro.org>
On 26/10/2026 05:48, Amir Ayupov wrote:
> From: Leo Yan <leo.yan(a)arm.com>
>
> 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(a)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 |
Reviewed-by: James Clark <james.clark(a)linaro.org>
On 25/10/2026 06:38, Amir Ayupov wrote:
> On Mon, 12 Oct 2026 22:09:35 -0300 Daniel Pereira <danielmaraboo(a)gmail.com> wrote:
>
>> 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'd rather drop PMU specifiers as this is not something this patch
> series focuses on, and examples above avoid them too.
I agree. Making the docs overly verbose makes them less useful. And I
can't see a use case where a user would get stuck converting this
example to their own system.
>>
>> 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(a)gmail.com>
>>
>> Thanks,
>> Daniel
>
> Sent using hkml (https://github.com/sjp38/hackermail)
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(a)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(a)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
On Wed, Oct 21, 2026 at 10:03:22AM +0800, Johnny.Fan wrote:
> These synthetic devices have no fwnode, so the firmware-described
> IRQ affinity cannot tell which CPUs implement the feature. Pass the
> CPU mask as platform data and have the drivers prefer it over the
> IRQ affinity when present.
Could the MADT-derived CPU masks be exposed through
platform_get_irq_affinity(), so SPE and TRBE can continue using the
common interface without fetching ACPI-specific data?
TBC, I don't know ACPI or GIC. I just thought it might be a neat
approach.
> Apply the same treatment to TRBE, which shares this registration
> code. TRBE must also pass a stable copy of the mask to
> request_percpu_irq_affinity(), since supported_cpus is pruned as
> CPUs are probed.
I wouldn't expect any changes to the SPE or TRBE drivers if
platform_get_irq_affinity() can return the correct CPU mask.
Thanks,
Leo