hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
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,17 +105,12 @@
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;
110
- unsigned long flags;
111
- int pc;
112
-
113
- pc = preempt_count();
114
- local_save_flags(flags);
115111
116112 event = trace_buffer_lock_reserve(buffer, TRACE_HWLAT, sizeof(*entry),
117
- flags, pc);
113
+ tracing_gen_ctx());
118114 if (!event)
119115 return;
120116 entry = ring_buffer_event_data(event);
....@@ -124,6 +120,7 @@
124120 entry->timestamp = sample->timestamp;
125121 entry->nmi_total_ts = sample->nmi_total_ts;
126122 entry->nmi_count = sample->nmi_count;
123
+ entry->count = sample->count;
127124
128125 if (!call_filter_check_discard(call, entry, buffer, event))
129126 trace_buffer_unlock_commit_nostack(buffer, event);
....@@ -167,12 +164,14 @@
167164 static int get_sample(void)
168165 {
169166 struct trace_array *tr = hwlat_trace;
167
+ struct hwlat_sample s;
170168 time_type start, t1, t2, last_t2;
171
- s64 diff, total, last_total = 0;
169
+ s64 diff, outer_diff, total, last_total = 0;
172170 u64 sample = 0;
173171 u64 thresh = tracing_thresh;
174172 u64 outer_sample = 0;
175173 int ret = -1;
174
+ unsigned int count = 0;
176175
177176 do_div(thresh, NSEC_PER_USEC); /* modifies interval value */
178177
....@@ -186,6 +185,7 @@
186185
187186 init_time(last_t2, 0);
188187 start = time_get(); /* start timestamp */
188
+ outer_diff = 0;
189189
190190 do {
191191
....@@ -194,14 +194,14 @@
194194
195195 if (time_u64(last_t2)) {
196196 /* Check the delta from outer loop (t2 to next t1) */
197
- diff = time_to_us(time_sub(t1, last_t2));
197
+ outer_diff = time_to_us(time_sub(t1, last_t2));
198198 /* This shouldn't happen */
199
- if (diff < 0) {
199
+ if (outer_diff < 0) {
200200 pr_err(BANNER "time running backwards\n");
201201 goto out;
202202 }
203
- if (diff > outer_sample)
204
- outer_sample = diff;
203
+ if (outer_diff > outer_sample)
204
+ outer_sample = outer_diff;
205205 }
206206 last_t2 = t2;
207207
....@@ -216,6 +216,12 @@
216216
217217 /* This checks the inner loop (t1 to t2) */
218218 diff = time_to_us(time_sub(t2, t1)); /* current diff */
219
+
220
+ if (diff > thresh || outer_diff > thresh) {
221
+ if (!count)
222
+ ktime_get_real_ts64(&s.timestamp);
223
+ count++;
224
+ }
219225
220226 /* This shouldn't happen */
221227 if (diff < 0) {
....@@ -236,7 +242,7 @@
236242
237243 /* If we exceed the threshold value, we have found a hardware latency */
238244 if (sample > thresh || outer_sample > thresh) {
239
- struct hwlat_sample s;
245
+ u64 latency;
240246
241247 ret = 1;
242248
....@@ -248,16 +254,18 @@
248254 s.seqnum = hwlat_data.count;
249255 s.duration = sample;
250256 s.outer_duration = outer_sample;
251
- ktime_get_real_ts64(&s.timestamp);
252257 s.nmi_total_ts = nmi_total_ts;
253258 s.nmi_count = nmi_count;
259
+ s.count = count;
254260 trace_hwlat_sample(&s);
255261
262
+ latency = max(sample, outer_sample);
263
+
256264 /* 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;
265
+ if (latency > tr->max_latency) {
266
+ tr->max_latency = latency;
267
+ latency_fsnotify(tr);
268
+ }
261269 }
262270
263271 out:
....@@ -277,7 +285,7 @@
277285 return;
278286 /*
279287 * If for some reason the user modifies the CPU affinity
280
- * of this thread, than stop migrating for the duration
288
+ * of this thread, then stop migrating for the duration
281289 * of the current test.
282290 */
283291 if (!cpumask_equal(current_mask, current->cpus_ptr))
....@@ -359,7 +367,6 @@
359367 return 0;
360368
361369 /* Just pick the first CPU on first iteration */
362
- current_mask = &save_cpumask;
363370 get_online_cpus();
364371 cpumask_and(current_mask, cpu_online_mask, tr->tracing_cpumask);
365372 put_online_cpus();
....@@ -526,14 +533,14 @@
526533 */
527534 static int init_tracefs(void)
528535 {
529
- struct dentry *d_tracer;
536
+ int ret;
530537 struct dentry *top_dir;
531538
532
- d_tracer = tracing_init_dentry();
533
- if (IS_ERR(d_tracer))
539
+ ret = tracing_init_dentry();
540
+ if (ret)
534541 return -ENOMEM;
535542
536
- top_dir = tracefs_create_dir("hwlat_detector", d_tracer);
543
+ top_dir = tracefs_create_dir("hwlat_detector", NULL);
537544 if (!top_dir)
538545 return -ENOMEM;
539546
....@@ -554,7 +561,7 @@
554561 return 0;
555562
556563 err:
557
- tracefs_remove_recursive(top_dir);
564
+ tracefs_remove(top_dir);
558565 return -ENOMEM;
559566 }
560567