Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

James Clark and committed by
Arnaldo Carvalho de Melo
35c51f83 3963d84b

+68 -84
+68 -84
tools/perf/arch/arm/util/cs-etm.c
··· 69 69 static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu); 70 70 static bool cs_etm_is_ete(struct auxtrace_record *itr, int cpu); 71 71 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) 74 74 { 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; 77 78 char path[PATH_MAX]; 78 - int err = -EINVAL; 79 + int err; 79 80 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")); 81 85 82 - ptr = container_of(itr, struct cs_etm_recording, itr); 83 - cs_etm_pmu = ptr->cs_etm_pmu; 86 + if (!contextid) 87 + return 0; 84 88 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 + } 87 95 88 96 /* Get a handle on TRCIDR2 */ 89 97 snprintf(path, PATH_MAX, "cpu%d/%s", ··· 100 92 101 93 /* There was a problem reading the file, bailing out */ 102 94 if (err != 1) { 103 - pr_err("%s: can't read file %s\n", 104 - CORESIGHT_ETM_PMU_NAME, path); 105 - goto out; 95 + pr_err("%s: can't read file %s\n", CORESIGHT_ETM_PMU_NAME, 96 + path); 97 + return err; 106 98 } 107 99 108 - /* User has configured for PID tracing, respects it. */ 109 - contextid = evsel->core.attr.config & 110 - (BIT(ETM_OPT_CTXTID) | BIT(ETM_OPT_CTXTID2)); 111 - 112 - /* 113 - * If user doesn't configure the contextid format, parse PMU format and 114 - * enable PID tracing according to the "contextid" format bits: 115 - * 116 - * If bit ETM_OPT_CTXTID is set, trace CONTEXTIDR_EL1; 117 - * If bit ETM_OPT_CTXTID2 is set, trace CONTEXTIDR_EL2. 118 - */ 119 - if (!contextid) 120 - contextid = perf_pmu__format_bits(&cs_etm_pmu->format, 121 - "contextid"); 122 - 123 - if (contextid & BIT(ETM_OPT_CTXTID)) { 100 + if (contextid & 101 + perf_pmu__format_bits(&cs_etm_pmu->format, "contextid1")) { 124 102 /* 125 103 * TRCIDR2.CIDSIZE, bit [9-5], indicates whether contextID 126 104 * tracing is supported: ··· 116 122 */ 117 123 val = BMVAL(val, 5, 9); 118 124 if (!val || val != 0x4) { 119 - pr_err("%s: CONTEXTIDR_EL1 isn't supported\n", 120 - CORESIGHT_ETM_PMU_NAME); 121 - err = -EINVAL; 122 - goto out; 125 + pr_err("%s: CONTEXTIDR_EL1 isn't supported, disable with %s/contextid1=0/\n", 126 + CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME); 127 + return -EINVAL; 123 128 } 124 129 } 125 130 126 - if (contextid & BIT(ETM_OPT_CTXTID2)) { 131 + if (contextid & 132 + perf_pmu__format_bits(&cs_etm_pmu->format, "contextid2")) { 127 133 /* 128 134 * TRCIDR2.VMIDOPT[30:29] != 0 and 129 135 * TRCIDR2.VMIDSIZE[14:10] == 0b00100 (32bit virtual contextid) ··· 132 138 * Any value of VMIDSIZE >= 4 (i.e, > 32bit) is fine for us. 133 139 */ 134 140 if (!BMVAL(val, 29, 30) || BMVAL(val, 10, 14) < 4) { 135 - pr_err("%s: CONTEXTIDR_EL2 isn't supported\n", 136 - CORESIGHT_ETM_PMU_NAME); 137 - err = -EINVAL; 138 - goto out; 141 + pr_err("%s: CONTEXTIDR_EL2 isn't supported, disable with %s/contextid2=0/\n", 142 + CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME); 143 + return -EINVAL; 139 144 } 140 145 } 141 146 142 - /* All good, let the kernel know */ 143 - evsel->core.attr.config |= contextid; 144 - err = 0; 145 - 146 - out: 147 - return err; 147 + return 0; 148 148 } 149 149 150 - static int cs_etm_set_timestamp(struct auxtrace_record *itr, 151 - struct evsel *evsel, int cpu) 150 + static int cs_etm_validate_timestamp(struct auxtrace_record *itr, 151 + struct evsel *evsel, int cpu) 152 152 { 153 - struct cs_etm_recording *ptr; 154 - struct perf_pmu *cs_etm_pmu; 153 + struct cs_etm_recording *ptr = 154 + container_of(itr, struct cs_etm_recording, itr); 155 + struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; 155 156 char path[PATH_MAX]; 156 - int err = -EINVAL; 157 + int err; 157 158 u32 val; 158 159 159 - ptr = container_of(itr, struct cs_etm_recording, itr); 160 - cs_etm_pmu = ptr->cs_etm_pmu; 160 + if (!(evsel->core.attr.config & 161 + perf_pmu__format_bits(&cs_etm_pmu->format, "timestamp"))) 162 + return 0; 161 163 162 - if (!cs_etm_is_etmv4(itr, cpu)) 163 - goto out; 164 + if (!cs_etm_is_etmv4(itr, cpu)) { 165 + pr_err("%s: timestamp not supported in ETMv3, disable with %s/timestamp=0/\n", 166 + CORESIGHT_ETM_PMU_NAME, CORESIGHT_ETM_PMU_NAME); 167 + return -EINVAL; 168 + } 164 169 165 170 /* Get a handle on TRCIRD0 */ 166 171 snprintf(path, PATH_MAX, "cpu%d/%s", ··· 170 177 if (err != 1) { 171 178 pr_err("%s: can't read file %s\n", 172 179 CORESIGHT_ETM_PMU_NAME, path); 173 - goto out; 180 + return err; 174 181 } 175 182 176 183 /* ··· 182 189 */ 183 190 val &= GENMASK(28, 24); 184 191 if (!val) { 185 - err = -EINVAL; 186 - goto out; 192 + return -EINVAL; 187 193 } 188 194 189 - /* All good, let the kernel know */ 190 - evsel->core.attr.config |= (1 << ETM_OPT_TS); 191 - err = 0; 192 - 193 - out: 194 - return err; 195 + return 0; 195 196 } 196 197 197 - #define ETM_SET_OPT_CTXTID (1 << 0) 198 - #define ETM_SET_OPT_TS (1 << 1) 199 - #define ETM_SET_OPT_MASK (ETM_SET_OPT_CTXTID | ETM_SET_OPT_TS) 200 - 201 - static int cs_etm_set_option(struct auxtrace_record *itr, 202 - struct evsel *evsel, u32 option) 198 + /* 199 + * Check whether the requested timestamp and contextid options should be 200 + * available on all requested CPUs and if not, tell the user how to override. 201 + * The kernel will silently disable any unavailable options so a warning here 202 + * first is better. In theory the kernel could still disable the option for 203 + * some other reason so this is best effort only. 204 + */ 205 + static int cs_etm_validate_config(struct auxtrace_record *itr, 206 + struct evsel *evsel) 203 207 { 204 208 int i, err = -EINVAL; 205 209 struct perf_cpu_map *event_cpus = evsel->evlist->core.user_requested_cpus; ··· 210 220 !perf_cpu_map__has(online_cpus, cpu)) 211 221 continue; 212 222 213 - if (option & BIT(ETM_OPT_CTXTID)) { 214 - err = cs_etm_set_context_id(itr, evsel, i); 215 - if (err) 216 - goto out; 217 - } 218 - if (option & BIT(ETM_OPT_TS)) { 219 - err = cs_etm_set_timestamp(itr, evsel, i); 220 - if (err) 221 - goto out; 222 - } 223 - if (option & ~(BIT(ETM_OPT_CTXTID) | BIT(ETM_OPT_TS))) 224 - /* Nothing else is currently supported */ 223 + err = cs_etm_validate_context_id(itr, evsel, i); 224 + if (err) 225 + goto out; 226 + err = cs_etm_validate_timestamp(itr, evsel, i); 227 + if (err) 225 228 goto out; 226 229 } 227 230 ··· 430 447 * when a context switch happened. 431 448 */ 432 449 if (!perf_cpu_map__empty(cpus)) { 433 - err = cs_etm_set_option(itr, cs_etm_evsel, 434 - BIT(ETM_OPT_CTXTID) | BIT(ETM_OPT_TS)); 435 - if (err) 436 - goto out; 450 + cs_etm_evsel->core.attr.config |= 451 + perf_pmu__format_bits(&cs_etm_pmu->format, "timestamp"); 452 + cs_etm_evsel->core.attr.config |= 453 + perf_pmu__format_bits(&cs_etm_pmu->format, "contextid"); 437 454 } 438 455 439 456 /* Add dummy event to keep tracking */ ··· 449 466 if (!perf_cpu_map__empty(cpus)) 450 467 evsel__set_sample_bit(evsel, TIME); 451 468 469 + err = cs_etm_validate_config(itr, cs_etm_evsel); 452 470 out: 453 471 return err; 454 472 }