hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/kernel/trace/trace_hwlat.c
....@@ -1,6 +1,6 @@
11 // SPDX-License-Identifier: GPL-2.0
22 /*
3
- * trace_hwlatdetect.c - A simple Hardware Latency detector.
3
+ * trace_hwlat.c - A simple Hardware Latency detector.
44 *
55 * Use this tracer to detect large system latencies induced by the behavior of
66 * certain underlying system hardware or firmware, independent of Linux itself.
....@@ -83,6 +83,7 @@
8383 u64 nmi_total_ts; /* Total time spent in NMIs */
8484 struct timespec64 timestamp; /* wall time */
8585 int nmi_count; /* # NMIs during this sample */
86
+ int count; /* # of iteratons over threash */
8687 };
8788
8889 /* keep the global state somewhere. */
....@@ -104,7 +105,7 @@
104105 {
105106 struct trace_array *tr = hwlat_trace;
106107 struct trace_event_call *call = &event_hwlat;
107
- struct ring_buffer *buffer = tr->trace_buffer.buffer;
108
+ struct trace_buffer *buffer = tr->array_buffer.buffer;
108109 struct ring_buffer_event *event;
109110 struct hwlat_entry *entry;
110111 unsigned long flags;
....@@ -124,6 +125,7 @@
124125 entry->timestamp = sample->timestamp;
125126 entry->nmi_total_ts = sample->nmi_total_ts;
126127 entry->nmi_count = sample->nmi_count;
128
+ entry->count = sample->count;
127129
128130 if (!call_filter_check_discard(call, entry, buffer, event))
129131 trace_buffer_unlock_commit_nostack(buffer, event);
....@@ -167,12 +169,14 @@
167169 static int get_sample(void)
168170 {
169171 struct trace_array *tr = hwlat_trace;
172
+ struct hwlat_sample s;
170173 time_type start, t1, t2, last_t2;
171
- s64 diff, total, last_total = 0;
174
+ s64 diff, outer_diff, total, last_total = 0;
172175 u64 sample = 0;
173176 u64 thresh = tracing_thresh;
174177 u64 outer_sample = 0;
175178 int ret = -1;
179
+ unsigned int count = 0;
176180
177181 do_div(thresh, NSEC_PER_USEC); /* modifies interval value */
178182
....@@ -186,6 +190,7 @@
186190
187191 init_time(last_t2, 0);
188192 start = time_get(); /* start timestamp */
193
+ outer_diff = 0;
189194
190195 do {
191196
....@@ -194,14 +199,14 @@
194199
195200 if (time_u64(last_t2)) {
196201 /* Check the delta from outer loop (t2 to next t1) */
197
- diff = time_to_us(time_sub(t1, last_t2));
202
+ outer_diff = time_to_us(time_sub(t1, last_t2));
198203 /* This shouldn't happen */
199
- if (diff < 0) {
204
+ if (outer_diff < 0) {
200205 pr_err(BANNER "time running backwards\n");
201206 goto out;
202207 }
203
- if (diff > outer_sample)
204
- outer_sample = diff;
208
+ if (outer_diff > outer_sample)
209
+ outer_sample = outer_diff;
205210 }
206211 last_t2 = t2;
207212
....@@ -216,6 +221,12 @@
216221
217222 /* This checks the inner loop (t1 to t2) */
218223 diff = time_to_us(time_sub(t2, t1)); /* current diff */
224
+
225
+ if (diff > thresh || outer_diff > thresh) {
226
+ if (!count)
227
+ ktime_get_real_ts64(&s.timestamp);
228
+ count++;
229
+ }
219230
220231 /* This shouldn't happen */
221232 if (diff < 0) {
....@@ -236,7 +247,7 @@
236247
237248 /* If we exceed the threshold value, we have found a hardware latency */
238249 if (sample > thresh || outer_sample > thresh) {
239
- struct hwlat_sample s;
250
+ u64 latency;
240251
241252 ret = 1;
242253
....@@ -248,16 +259,18 @@
248259 s.seqnum = hwlat_data.count;
249260 s.duration = sample;
250261 s.outer_duration = outer_sample;
251
- ktime_get_real_ts64(&s.timestamp);
252262 s.nmi_total_ts = nmi_total_ts;
253263 s.nmi_count = nmi_count;
264
+ s.count = count;
254265 trace_hwlat_sample(&s);
255266
267
+ latency = max(sample, outer_sample);
268
+
256269 /* Keep a running maximum ever recorded hardware latency */
257
- if (sample > tr->max_latency)
258
- tr->max_latency = sample;
259
- if (outer_sample > tr->max_latency)
260
- tr->max_latency = outer_sample;
270
+ if (latency > tr->max_latency) {
271
+ tr->max_latency = latency;
272
+ latency_fsnotify(tr);
273
+ }
261274 }
262275
263276 out:
....@@ -277,10 +290,10 @@
277290 return;
278291 /*
279292 * If for some reason the user modifies the CPU affinity
280
- * of this thread, than stop migrating for the duration
293
+ * of this thread, then stop migrating for the duration
281294 * of the current test.
282295 */
283
- if (!cpumask_equal(current_mask, &current->cpus_allowed))
296
+ if (!cpumask_equal(current_mask, current->cpus_ptr))
284297 goto disable;
285298
286299 get_online_cpus();
....@@ -359,7 +372,6 @@
359372 return 0;
360373
361374 /* Just pick the first CPU on first iteration */
362
- current_mask = &save_cpumask;
363375 get_online_cpus();
364376 cpumask_and(current_mask, cpu_online_mask, tr->tracing_cpumask);
365377 put_online_cpus();
....@@ -526,14 +538,14 @@
526538 */
527539 static int init_tracefs(void)
528540 {
529
- struct dentry *d_tracer;
541
+ int ret;
530542 struct dentry *top_dir;
531543
532
- d_tracer = tracing_init_dentry();
533
- if (IS_ERR(d_tracer))
544
+ ret = tracing_init_dentry();
545
+ if (ret)
534546 return -ENOMEM;
535547
536
- top_dir = tracefs_create_dir("hwlat_detector", d_tracer);
548
+ top_dir = tracefs_create_dir("hwlat_detector", NULL);
537549 if (!top_dir)
538550 return -ENOMEM;
539551
....@@ -554,7 +566,7 @@
554566 return 0;
555567
556568 err:
557
- tracefs_remove_recursive(top_dir);
569
+ tracefs_remove(top_dir);
558570 return -ENOMEM;
559571 }
560572