Skip to content

Commit 35c51f8

Browse files
James-A-Clarkacmel
authored andcommitted
perf cs-etm: Validate options after applying them
Currently the cs_etm_set_option() function both validates and applies the config options. Because it's only called when they are added automatically, there are some paths where the user can apply the option on the command line and skip the validation. By moving it to the end it covers both cases. Also, options don't need to be re-applied anyway, Perf handles parsing and applying the config terms automatically. Signed-off-by: James Clark <james.clark@arm.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Denis Nikitin <denik@google.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: John Garry <john.g.garry@oracle.com> Cc: Leo Yan <leo.yan@linaro.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Mathieu Poirier <mathieu.poirier@linaro.org> Cc: Mike Leach <mike.leach@linaro.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Suzuki Poulouse <suzuki.poulose@arm.com> Cc: Will Deacon <will@kernel.org> Cc: Yang Shi <shy828301@gmail.com> Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20230424134748.228137-5-james.clark@arm.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
1 parent 3963d84 commit 35c51f8

1 file changed

Lines changed: 68 additions & 84 deletions

File tree

tools/perf/arch/arm/util/cs-etm.c

Lines changed: 68 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -69,21 +69,29 @@ static const char * const metadata_ete_ro[] = {
6969
static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu);
7070
static bool cs_etm_is_ete(struct auxtrace_record *itr, int cpu);
7171

72-
static int cs_etm_set_context_id(struct auxtrace_record *itr,
73-
struct evsel *evsel, int cpu)
72+
static int cs_etm_validate_context_id(struct auxtrace_record *itr,
73+
struct evsel *evsel, int cpu)
7474
{
75-
struct cs_etm_recording *ptr;
76-
struct perf_pmu *cs_etm_pmu;
75+
struct cs_etm_recording *ptr =
76+
container_of(itr, struct cs_etm_recording, itr);
77+
struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
7778
char path[PATH_MAX];
78-
int err = -EINVAL;
79+
int err;
7980
u32 val;
80-
u64 contextid;
81+
u64 contextid =
82+
evsel->core.attr.config &
83+
(perf_pmu__format_bits(&cs_etm_pmu->format, "contextid1") |
84+
perf_pmu__format_bits(&cs_etm_pmu->format, "contextid2"));
8185

82-
ptr = container_of(itr, struct cs_etm_recording, itr);
83-
cs_etm_pmu = ptr->cs_etm_pmu;
86+
if (!contextid)
87+
return 0;
8488

85-
if (!cs_etm_is_etmv4(itr, cpu))
86-
goto out;
89+
/* Not supported in etmv3 */
90+
if (!cs_etm_is_etmv4(itr, cpu)) {
91+
pr_err("%s: contextid not supported in ETMv3, disable with %s/contextid=0/\n",
92+
CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME);
93+
return -EINVAL;
94+
}
8795

8896
/* Get a handle on TRCIDR2 */
8997
snprintf(path, PATH_MAX, "cpu%d/%s",
@@ -92,27 +100,13 @@ static int cs_etm_set_context_id(struct auxtrace_record *itr,
92100

93101
/* There was a problem reading the file, bailing out */
94102
if (err != 1) {
95-
pr_err("%s: can't read file %s\n",
96-
CORESIGHT_ETM_PMU_NAME, path);
97-
goto out;
103+
pr_err("%s: can't read file %s\n", CORESIGHT_ETM_PMU_NAME,
104+
path);
105+
return err;
98106
}
99107

100-
/* User has configured for PID tracing, respects it. */
101-
contextid = evsel->core.attr.config &
102-
(BIT(ETM_OPT_CTXTID) | BIT(ETM_OPT_CTXTID2));
103-
104-
/*
105-
* If user doesn't configure the contextid format, parse PMU format and
106-
* enable PID tracing according to the "contextid" format bits:
107-
*
108-
* If bit ETM_OPT_CTXTID is set, trace CONTEXTIDR_EL1;
109-
* If bit ETM_OPT_CTXTID2 is set, trace CONTEXTIDR_EL2.
110-
*/
111-
if (!contextid)
112-
contextid = perf_pmu__format_bits(&cs_etm_pmu->format,
113-
"contextid");
114-
115-
if (contextid & BIT(ETM_OPT_CTXTID)) {
108+
if (contextid &
109+
perf_pmu__format_bits(&cs_etm_pmu->format, "contextid1")) {
116110
/*
117111
* TRCIDR2.CIDSIZE, bit [9-5], indicates whether contextID
118112
* tracing is supported:
@@ -122,14 +116,14 @@ static int cs_etm_set_context_id(struct auxtrace_record *itr,
122116
*/
123117
val = BMVAL(val, 5, 9);
124118
if (!val || val != 0x4) {
125-
pr_err("%s: CONTEXTIDR_EL1 isn't supported\n",
126-
CORESIGHT_ETM_PMU_NAME);
127-
err = -EINVAL;
128-
goto out;
119+
pr_err("%s: CONTEXTIDR_EL1 isn't supported, disable with %s/contextid1=0/\n",
120+
CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME);
121+
return -EINVAL;
129122
}
130123
}
131124

132-
if (contextid & BIT(ETM_OPT_CTXTID2)) {
125+
if (contextid &
126+
perf_pmu__format_bits(&cs_etm_pmu->format, "contextid2")) {
133127
/*
134128
* TRCIDR2.VMIDOPT[30:29] != 0 and
135129
* TRCIDR2.VMIDSIZE[14:10] == 0b00100 (32bit virtual contextid)
@@ -138,35 +132,34 @@ static int cs_etm_set_context_id(struct auxtrace_record *itr,
138132
* Any value of VMIDSIZE >= 4 (i.e, > 32bit) is fine for us.
139133
*/
140134
if (!BMVAL(val, 29, 30) || BMVAL(val, 10, 14) < 4) {
141-
pr_err("%s: CONTEXTIDR_EL2 isn't supported\n",
142-
CORESIGHT_ETM_PMU_NAME);
143-
err = -EINVAL;
144-
goto out;
135+
pr_err("%s: CONTEXTIDR_EL2 isn't supported, disable with %s/contextid2=0/\n",
136+
CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME);
137+
return -EINVAL;
145138
}
146139
}
147140

148-
/* All good, let the kernel know */
149-
evsel->core.attr.config |= contextid;
150-
err = 0;
151-
152-
out:
153-
return err;
141+
return 0;
154142
}
155143

156-
static int cs_etm_set_timestamp(struct auxtrace_record *itr,
157-
struct evsel *evsel, int cpu)
144+
static int cs_etm_validate_timestamp(struct auxtrace_record *itr,
145+
struct evsel *evsel, int cpu)
158146
{
159-
struct cs_etm_recording *ptr;
160-
struct perf_pmu *cs_etm_pmu;
147+
struct cs_etm_recording *ptr =
148+
container_of(itr, struct cs_etm_recording, itr);
149+
struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
161150
char path[PATH_MAX];
162-
int err = -EINVAL;
151+
int err;
163152
u32 val;
164153

165-
ptr = container_of(itr, struct cs_etm_recording, itr);
166-
cs_etm_pmu = ptr->cs_etm_pmu;
154+
if (!(evsel->core.attr.config &
155+
perf_pmu__format_bits(&cs_etm_pmu->format, "timestamp")))
156+
return 0;
167157

168-
if (!cs_etm_is_etmv4(itr, cpu))
169-
goto out;
158+
if (!cs_etm_is_etmv4(itr, cpu)) {
159+
pr_err("%s: timestamp not supported in ETMv3, disable with %s/timestamp=0/\n",
160+
CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME);
161+
return -EINVAL;
162+
}
170163

171164
/* Get a handle on TRCIRD0 */
172165
snprintf(path, PATH_MAX, "cpu%d/%s",
@@ -177,7 +170,7 @@ static int cs_etm_set_timestamp(struct auxtrace_record *itr,
177170
if (err != 1) {
178171
pr_err("%s: can't read file %s\n",
179172
CORESIGHT_ETM_PMU_NAME, path);
180-
goto out;
173+
return err;
181174
}
182175

183176
/*
@@ -189,24 +182,21 @@ static int cs_etm_set_timestamp(struct auxtrace_record *itr,
189182
*/
190183
val &= GENMASK(28, 24);
191184
if (!val) {
192-
err = -EINVAL;
193-
goto out;
185+
return -EINVAL;
194186
}
195187

196-
/* All good, let the kernel know */
197-
evsel->core.attr.config |= (1 << ETM_OPT_TS);
198-
err = 0;
199-
200-
out:
201-
return err;
188+
return 0;
202189
}
203190

204-
#define ETM_SET_OPT_CTXTID (1 << 0)
205-
#define ETM_SET_OPT_TS (1 << 1)
206-
#define ETM_SET_OPT_MASK (ETM_SET_OPT_CTXTID | ETM_SET_OPT_TS)
207-
208-
static int cs_etm_set_option(struct auxtrace_record *itr,
209-
struct evsel *evsel, u32 option)
191+
/*
192+
* Check whether the requested timestamp and contextid options should be
193+
* available on all requested CPUs and if not, tell the user how to override.
194+
* The kernel will silently disable any unavailable options so a warning here
195+
* first is better. In theory the kernel could still disable the option for
196+
* some other reason so this is best effort only.
197+
*/
198+
static int cs_etm_validate_config(struct auxtrace_record *itr,
199+
struct evsel *evsel)
210200
{
211201
int i, err = -EINVAL;
212202
struct perf_cpu_map *event_cpus = evsel->evlist->core.user_requested_cpus;
@@ -220,18 +210,11 @@ static int cs_etm_set_option(struct auxtrace_record *itr,
220210
!perf_cpu_map__has(online_cpus, cpu))
221211
continue;
222212

223-
if (option & BIT(ETM_OPT_CTXTID)) {
224-
err = cs_etm_set_context_id(itr, evsel, i);
225-
if (err)
226-
goto out;
227-
}
228-
if (option & BIT(ETM_OPT_TS)) {
229-
err = cs_etm_set_timestamp(itr, evsel, i);
230-
if (err)
231-
goto out;
232-
}
233-
if (option & ~(BIT(ETM_OPT_CTXTID) | BIT(ETM_OPT_TS)))
234-
/* Nothing else is currently supported */
213+
err = cs_etm_validate_context_id(itr, evsel, i);
214+
if (err)
215+
goto out;
216+
err = cs_etm_validate_timestamp(itr, evsel, i);
217+
if (err)
235218
goto out;
236219
}
237220

@@ -447,10 +430,10 @@ static int cs_etm_recording_options(struct auxtrace_record *itr,
447430
* when a context switch happened.
448431
*/
449432
if (!perf_cpu_map__empty(cpus)) {
450-
err = cs_etm_set_option(itr, cs_etm_evsel,
451-
BIT(ETM_OPT_CTXTID) | BIT(ETM_OPT_TS));
452-
if (err)
453-
goto out;
433+
cs_etm_evsel->core.attr.config |=
434+
perf_pmu__format_bits(&cs_etm_pmu->format, "timestamp");
435+
cs_etm_evsel->core.attr.config |=
436+
perf_pmu__format_bits(&cs_etm_pmu->format, "contextid");
454437
}
455438

456439
/* Add dummy event to keep tracking */
@@ -466,6 +449,7 @@ static int cs_etm_recording_options(struct auxtrace_record *itr,
466449
if (!perf_cpu_map__empty(cpus))
467450
evsel__set_sample_bit(evsel, TIME);
468451

452+
err = cs_etm_validate_config(itr, cs_etm_evsel);
469453
out:
470454
return err;
471455
}

0 commit comments

Comments
 (0)