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 --- drivers/hwtracing/coresight/coresight-etm4x-core.c | 15 +++++++++-- .../hwtracing/coresight/coresight-etm4x-sysfs.c | 29 ++++++++++++---------- 2 files changed, 29 insertions(+), 15 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c index e21be6468e9544fe6e22f524de4fef9f89d7484f..b0e286f487017a4155595f14cbb9c9c33b17dc6b 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,19 @@ 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; + + /* + * See ARM IHI0064H.b, sections 7.3.32 (TRCIDR0) and 7.3.36 (TRCIDR4). + * + * Before ETMv4.3, one event is always implemented. For ETM v4.3 and + * later, NUMRSPAIR == 0 indicates that no events are implemented. + * Otherwise, NUMEVENT encodes the number of events minus one. + */ + 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 db9e603f97ba82cd608d3d61881fe8153db020ff..fb38f0102290a53a681934c827abf107c141a740 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 |
--- base-commit: 343cfcbb3ecfdb80aa576a428cfa3b65ad783842 change-id: 20261022-arm_cs_fix_etm4_event_count-49f384a2f6a7
Best regards,