@@ -69,21 +69,29 @@ static const char * const metadata_ete_ro[] = {
6969static bool cs_etm_is_etmv4 (struct auxtrace_record * itr , int cpu );
7070static 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 );
469453out :
470454 return err ;
471455}
0 commit comments