Some HW has static trace id which cannot be changed via software programming.
For this case, configure the trace id in device tree with
"trace-id = <xxx>", and call coresight_trace_id_reserve_system_id in
device probe function. The id will be reserved for the HW all the time
if the device is probed.
Mao Jinlong (3):
dt-bindings: arm: Add trace-id for coresight dummy source
coresight: Add reserve trace id support
coresight: dummy: Add reserve atid support for dummy source
.../sysfs-bus-coresight-devices-dummy-source | 15 +++++
.../arm/arm,coresight-dummy-source.yaml | 6 ++
drivers/hwtracing/coresight/coresight-dummy.c | 56 +++++++++++++++++--
.../hwtracing/coresight/coresight-platform.c | 26 +++++++++
.../hwtracing/coresight/coresight-trace-id.c | 24 ++++++++
.../hwtracing/coresight/coresight-trace-id.h | 11 ++++
include/linux/coresight.h | 1 +
7 files changed, 135 insertions(+), 4 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-bus-coresight-devices-dummy-source
--
2.41.0
This will allow sessions with more than CORESIGHT_TRACE_IDS_MAX ETMs
as long as there are fewer than that many ETMs connected to each sink.
Each sink owns its own trace ID map, and any Perf session connecting to
that sink will allocate from it, even if the sink is currently in use by
other users. This is similar to the existing behavior where the dynamic
trace IDs are constant as long as there is any concurrent Perf session
active. It's not completely optimal because slightly more IDs will be
used than necessary, but the optimal solution involves tracking the PIDs
of each session and allocating ID maps based on the session owner. This
is difficult to do with the combination of per-thread and per-cpu modes
and some scheduling issues. The complexity of this isn't likely to worth
it because even with multiple users they'd just see a difference in the
ordering of ID allocations rather than hitting any limits (unless the
hardware does have too many ETMs connected to one sink).
Per-thread mode works but only until there are any overlapping IDs, at
which point Perf will error out. Both per-thread mode and sysfs mode are
left to future changes, but both can be added on top of this initial
implementation and only sysfs mode requires further driver changes.
The HW_ID version field hasn't been bumped in order to not break Perf
which already has an error condition for other values of that field.
Instead a new minor version has been added which signifies that there
are new fields but the old fields are backwards compatible.
James Clark (17):
perf cs-etm: Print error for new PERF_RECORD_AUX_OUTPUT_HW_ID versions
perf auxtrace: Allow number of queues to be specified
perf: cs-etm: Create decoders after both AUX and HW_ID search passes
perf: cs-etm: Allocate queues for all CPUs
perf: cs-etm: Move traceid_list to each queue
perf: cs-etm: Create decoders based on the trace ID mappings
perf: cs-etm: Support version 0.1 of HW_ID packets
coresight: Remove unused stubs
coresight: Clarify comments around the PID of the sink owner
coresight: Move struct coresight_trace_id_map to common header
coresight: Expose map argument in trace ID API
coresight: Make CPU id map a property of a trace ID map
coresight: Pass trace ID map into source enable
coresight: Use per-sink trace ID maps for Perf sessions
coresight: Remove pending trace ID release mechanism
coresight: Re-emit trace IDs when the sink changes in per-thread mode
coresight: Emit HW_IDs for all ETMs that are using the sink
drivers/hwtracing/coresight/coresight-core.c | 10 +
drivers/hwtracing/coresight/coresight-dummy.c | 3 +-
.../hwtracing/coresight/coresight-etm-perf.c | 82 ++-
.../hwtracing/coresight/coresight-etm-perf.h | 20 +-
.../coresight/coresight-etm3x-core.c | 14 +-
.../coresight/coresight-etm4x-core.c | 14 +-
drivers/hwtracing/coresight/coresight-stm.c | 3 +-
drivers/hwtracing/coresight/coresight-sysfs.c | 3 +-
.../hwtracing/coresight/coresight-tmc-etr.c | 5 +-
drivers/hwtracing/coresight/coresight-tmc.h | 5 +-
drivers/hwtracing/coresight/coresight-tpdm.c | 3 +-
.../hwtracing/coresight/coresight-trace-id.c | 107 +--
.../hwtracing/coresight/coresight-trace-id.h | 57 +-
include/linux/coresight-pmu.h | 17 +-
include/linux/coresight.h | 20 +-
tools/include/linux/coresight-pmu.h | 17 +-
tools/perf/util/auxtrace.c | 9 +-
tools/perf/util/auxtrace.h | 1 +
.../perf/util/cs-etm-decoder/cs-etm-decoder.c | 28 +-
tools/perf/util/cs-etm.c | 617 ++++++++++++------
tools/perf/util/cs-etm.h | 2 +-
21 files changed, 633 insertions(+), 404 deletions(-)
--
2.34.1
Changes since v1:
* Add a commit to use struct perf_cpu in place of some of the ints
* Add a commit to remove repeated fetches of the ETM PMU
James Clark (3):
perf cs-etm: Use struct perf_cpu as much as possible
perf cs-etm: Remove repeated fetches of the ETM PMU
perf cs-etm: Improve version detection and error reporting
tools/perf/arch/arm/util/cs-etm.c | 287 +++++++++++++++---------------
1 file changed, 139 insertions(+), 148 deletions(-)
--
2.34.1
This detects and enables the scatter gather capability (SG) on ACPI based
Soc-400 TMC ETR devices via a new property called 'arm-armhc97c-sg-enable'.
The updated ACPI spec can be found below, which contains this new property.
https://developer.arm.com/documentation/den0067/latest/
This preserves current handling for the property 'arm,scatter-gather' both
on ACPI and DT based platforms i.e the presence of the property is checked
instead of the value.
Cc: Suzuki K Poulose <suzuki.poulose(a)arm.com>
Cc: Mike Leach <mike.leach(a)linaro.org>
Cc: James Clark <james.clark(a)arm.com>
Cc: Alexander Shishkin <alexander.shishkin(a)linux.intel.com>
Cc: coresight(a)lists.linaro.org
Cc: linux-arm-kernel(a)lists.infradead.org
Cc: linux-kernel(a)vger.kernel.org
Signed-off-by: Anshuman Khandual <anshuman.khandual(a)arm.com>
---
.../hwtracing/coresight/coresight-tmc-core.c | 28 ++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
index 72005b0c633e..2b277499b59a 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-core.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
@@ -4,6 +4,7 @@
* Description: CoreSight Trace Memory Controller driver
*/
+#include <linux/acpi.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
@@ -360,7 +361,32 @@ static const struct attribute_group *coresight_etr_groups[] = {
static inline bool tmc_etr_can_use_sg(struct device *dev)
{
- return fwnode_property_present(dev->fwnode, "arm,scatter-gather");
+ int ret;
+ u8 val_u8;
+
+ /*
+ * Presence of the property 'arm,scatter-gather' is checked
+ * on the platform for the feature support, rather than its
+ * value.
+ */
+ if (is_of_node(dev->fwnode)) {
+ return fwnode_property_present(dev->fwnode, "arm,scatter-gather");
+ } else if (is_acpi_device_node(dev->fwnode)) {
+ /*
+ * TMC_DEVID_NOSCAT test in tmc_etr_setup_caps(), has already ensured
+ * this property is only checked for Coresight SoC 400 TMC configured
+ * as ETR.
+ */
+ ret = fwnode_property_read_u8(dev->fwnode, "arm-armhc97c-sg-enable", &val_u8);
+ if (!ret)
+ return !!val_u8;
+
+ if (fwnode_property_present(dev->fwnode, "arm,scatter-gather")) {
+ pr_warn_once("Deprecated ACPI property - arm,scatter-gather\n");
+ return true;
+ }
+ }
+ return false;
}
static inline bool tmc_etr_has_non_secure_access(struct tmc_drvdata *drvdata)
--
2.25.1
On 30/04/2024 17:22, Ian Rogers wrote:
> On Tue, Apr 30, 2024 at 6:32 AM James Clark <james.clark(a)arm.com> wrote:
>>
>> When the config validation functions are warning about ETMv3, they do it
>> based on "not ETMv4". If the drivers aren't all loaded or the hardware
>> doesn't support Coresight it will appear as "not ETMv4" and then Perf
>> will print the error message "... not supported in ETMv3 ..." which is
>> wrong and confusing.
>>
>> cs_etm_is_etmv4() is also misnamed because it also returns true for
>> ETE because ETE has a superset of the ETMv4 metadata files. Although
>> this was always done in the correct order so it wasn't a bug.
>>
>> Improve all this by making a single get version function which also
>> handles not present as a separate case. Change the ETMv3 error message
>> to only print when ETMv3 is detected, and add a new error message for
>> the not present case.
>>
>> Signed-off-by: James Clark <james.clark(a)arm.com>
>> ---
>> tools/perf/arch/arm/util/cs-etm.c | 64 +++++++++++++++++++++++--------
>> 1 file changed, 48 insertions(+), 16 deletions(-)
>>
>> diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c
>> index 07be32d99805..2763c6758b91 100644
>> --- a/tools/perf/arch/arm/util/cs-etm.c
>> +++ b/tools/perf/arch/arm/util/cs-etm.c
>> @@ -66,9 +66,25 @@ static const char * const metadata_ete_ro[] = {
>> [CS_ETE_TS_SOURCE] = "ts_source",
>> };
>>
>> -static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu);
>> +enum cs_etm_version { CS_NOT_PRESENT, CS_ETMV3, CS_ETMV4, CS_ETE };
>> +
>> +static bool cs_etm_pmu_file_present(struct auxtrace_record *itr, int cpu,
>> + const char *file);
>> static bool cs_etm_is_ete(struct auxtrace_record *itr, int cpu);
>>
>> +static enum cs_etm_version cs_etm_get_version(struct auxtrace_record *itr,
>> + int cpu)
>
> nit: perhaps use "struct perf_cpu" rather than "int cpu" for a little
> bit of type safety. Fwiw, most of the tool uses an index into a CPU
> map but then have labelled that index "cpu" which is confusing
> particularly in the uncore case, whilst a perf_cpu is never an index.
>
> Reviewed-by: Ian Rogers <irogers(a)google.com>
>
> Thanks,
> Ian
>
Yeah I will make that change. There are quite a few early conversions
from the struct to the int that can be pushed all the way down to file open.
>> +{
>> + if (cs_etm_is_ete(itr, cpu))
>> + return CS_ETE;
>> + else if (cs_etm_pmu_file_present(itr, cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR0]))
>> + return CS_ETMV4;
>> + else if (cs_etm_pmu_file_present(itr, cpu, metadata_etmv3_ro[CS_ETM_ETMCCER]))
>> + return CS_ETMV3;
>> +
>> + return CS_NOT_PRESENT;
>> +}
>> +
>> static int cs_etm_validate_context_id(struct auxtrace_record *itr,
>> struct evsel *evsel, int cpu)
>> {
>> @@ -87,7 +103,7 @@ static int cs_etm_validate_context_id(struct auxtrace_record *itr,
>> return 0;
>>
>> /* Not supported in etmv3 */
>> - if (!cs_etm_is_etmv4(itr, cpu)) {
>> + if (cs_etm_get_version(itr, cpu) == CS_ETMV3) {
>> pr_err("%s: contextid not supported in ETMv3, disable with %s/contextid=0/\n",
>> CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME);
>> return -EINVAL;
>> @@ -154,7 +170,7 @@ static int cs_etm_validate_timestamp(struct auxtrace_record *itr,
>> perf_pmu__format_bits(cs_etm_pmu, "timestamp")))
>> return 0;
>>
>> - if (!cs_etm_is_etmv4(itr, cpu)) {
>> + if (cs_etm_get_version(itr, cpu) == CS_ETMV3) {
>> pr_err("%s: timestamp not supported in ETMv3, disable with %s/timestamp=0/\n",
>> CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME);
>> return -EINVAL;
>> @@ -218,6 +234,11 @@ static int cs_etm_validate_config(struct auxtrace_record *itr,
>> }
>>
>> perf_cpu_map__for_each_cpu_skip_any(cpu, idx, intersect_cpus) {
>> + if (cs_etm_get_version(itr, cpu.cpu) == CS_NOT_PRESENT) {
>> + pr_err("%s: Not found on CPU %d. Check hardware and firmware support and that all Coresight drivers are loaded\n",
>> + CORESIGHT_ETM_PMU_NAME, cpu.cpu);
>> + return -EINVAL;
>> + }
>> err = cs_etm_validate_context_id(itr, evsel, cpu.cpu);
>> if (err)
>> break;
>> @@ -548,13 +569,13 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
>> /* Event can be "any" CPU so count all online CPUs. */
>> intersect_cpus = perf_cpu_map__new_online_cpus();
>> }
>> + /* Count number of each type of ETM. Don't count if that CPU has CS_NOT_PRESENT. */
>> perf_cpu_map__for_each_cpu_skip_any(cpu, idx, intersect_cpus) {
>> - if (cs_etm_is_ete(itr, cpu.cpu))
>> - ete++;
>> - else if (cs_etm_is_etmv4(itr, cpu.cpu))
>> - etmv4++;
>> - else
>> - etmv3++;
>> + enum cs_etm_version v = cs_etm_get_version(itr, cpu.cpu);
>> +
>> + ete += v == CS_ETE;
>> + etmv4 += v == CS_ETMV4;
>> + etmv3 += v == CS_ETMV3;
>> }
>> perf_cpu_map__put(intersect_cpus);
>>
>> @@ -564,7 +585,8 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
>> (etmv3 * CS_ETMV3_PRIV_SIZE));
>> }
>>
>> -static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu)
>> +static bool cs_etm_pmu_file_present(struct auxtrace_record *itr, int cpu,
>> + const char *file)
>> {
>> bool ret = false;
>> char path[PATH_MAX];
>> @@ -574,9 +596,7 @@ static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu)
>> container_of(itr, struct cs_etm_recording, itr);
>> struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
>>
>> - /* Take any of the RO files for ETMv4 and see if it present */
>> - snprintf(path, PATH_MAX, "cpu%d/%s",
>> - cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
>> + snprintf(path, PATH_MAX, "cpu%d/%s", cpu, file);
>> scan = perf_pmu__scan_file(cs_etm_pmu, path, "%x", &val);
>>
>> /* The file was read successfully, we have a winner */
>> @@ -735,21 +755,26 @@ static void cs_etm_get_metadata(int cpu, u32 *offset,
>> struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
>>
>> /* first see what kind of tracer this cpu is affined to */
>> - if (cs_etm_is_ete(itr, cpu)) {
>> + switch (cs_etm_get_version(itr, cpu)) {
>> + case CS_ETE:
>> magic = __perf_cs_ete_magic;
>> cs_etm_save_ete_header(&info->priv[*offset], itr, cpu);
>>
>> /* How much space was used */
>> increment = CS_ETE_PRIV_MAX;
>> nr_trc_params = CS_ETE_PRIV_MAX - CS_ETM_COMMON_BLK_MAX_V1;
>> - } else if (cs_etm_is_etmv4(itr, cpu)) {
>> + break;
>> +
>> + case CS_ETMV4:
>> magic = __perf_cs_etmv4_magic;
>> cs_etm_save_etmv4_header(&info->priv[*offset], itr, cpu);
>>
>> /* How much space was used */
>> increment = CS_ETMV4_PRIV_MAX;
>> nr_trc_params = CS_ETMV4_PRIV_MAX - CS_ETMV4_TRCCONFIGR;
>> - } else {
>> + break;
>> +
>> + case CS_ETMV3:
>> magic = __perf_cs_etmv3_magic;
>> /* Get configuration register */
>> info->priv[*offset + CS_ETM_ETMCR] = cs_etm_get_config(itr);
>> @@ -767,6 +792,13 @@ static void cs_etm_get_metadata(int cpu, u32 *offset,
>> /* How much space was used */
>> increment = CS_ETM_PRIV_MAX;
>> nr_trc_params = CS_ETM_PRIV_MAX - CS_ETM_ETMCR;
>> + break;
>> +
>> + default:
>> + case CS_NOT_PRESENT:
>> + /* Unreachable, CPUs already validated in cs_etm_validate_config() */
>> + assert(true);
>> + return;
>> }
>>
>> /* Build generic header portion */
>> --
>> 2.34.1
>>