trace_hwlat.c (e7c15cd8a113335cf7154f027c9c8da1a92238ee) trace_hwlat.c (0330f7aa8ee63d0c435c0cb4e47ea06235ee4b7f)
1/*
2 * trace_hwlatdetect.c - A simple Hardware Latency detector.
3 *
4 * Use this tracer to detect large system latencies induced by the behavior of
5 * certain underlying system hardware or firmware, independent of Linux itself.
6 * The code was developed originally to detect the presence of SMIs on Intel
7 * and AMD systems, although there is no dependency upon x86 herein.
8 *

--- 28 unchanged lines hidden (view full) ---

37 *
38 * This file is licensed under the terms of the GNU General Public
39 * License version 2. This program is licensed "as is" without any
40 * warranty of any kind, whether express or implied.
41 */
42#include <linux/kthread.h>
43#include <linux/tracefs.h>
44#include <linux/uaccess.h>
1/*
2 * trace_hwlatdetect.c - A simple Hardware Latency detector.
3 *
4 * Use this tracer to detect large system latencies induced by the behavior of
5 * certain underlying system hardware or firmware, independent of Linux itself.
6 * The code was developed originally to detect the presence of SMIs on Intel
7 * and AMD systems, although there is no dependency upon x86 herein.
8 *

--- 28 unchanged lines hidden (view full) ---

37 *
38 * This file is licensed under the terms of the GNU General Public
39 * License version 2. This program is licensed "as is" without any
40 * warranty of any kind, whether express or implied.
41 */
42#include <linux/kthread.h>
43#include <linux/tracefs.h>
44#include <linux/uaccess.h>
45#include <linux/cpumask.h>
45#include <linux/delay.h>
46#include "trace.h"
47
48static struct trace_array *hwlat_trace;
49
50#define U64STR_SIZE 22 /* 20 digits max */
51
52#define BANNER "hwlat_detector: "

--- 153 unchanged lines hidden (view full) ---

206 if (sample > tr->max_latency)
207 tr->max_latency = sample;
208 }
209
210out:
211 return ret;
212}
213
46#include <linux/delay.h>
47#include "trace.h"
48
49static struct trace_array *hwlat_trace;
50
51#define U64STR_SIZE 22 /* 20 digits max */
52
53#define BANNER "hwlat_detector: "

--- 153 unchanged lines hidden (view full) ---

207 if (sample > tr->max_latency)
208 tr->max_latency = sample;
209 }
210
211out:
212 return ret;
213}
214
215static struct cpumask save_cpumask;
216static bool disable_migrate;
217
218static void move_to_next_cpu(void)
219{
220 static struct cpumask *current_mask;
221 int next_cpu;
222
223 if (disable_migrate)
224 return;
225
226 /* Just pick the first CPU on first iteration */
227 if (!current_mask) {
228 current_mask = &save_cpumask;
229 get_online_cpus();
230 cpumask_and(current_mask, cpu_online_mask, tracing_buffer_mask);
231 put_online_cpus();
232 next_cpu = cpumask_first(current_mask);
233 goto set_affinity;
234 }
235
236 /*
237 * If for some reason the user modifies the CPU affinity
238 * of this thread, than stop migrating for the duration
239 * of the current test.
240 */
241 if (!cpumask_equal(current_mask, &current->cpus_allowed))
242 goto disable;
243
244 get_online_cpus();
245 cpumask_and(current_mask, cpu_online_mask, tracing_buffer_mask);
246 next_cpu = cpumask_next(smp_processor_id(), current_mask);
247 put_online_cpus();
248
249 if (next_cpu >= nr_cpu_ids)
250 next_cpu = cpumask_first(current_mask);
251
252 set_affinity:
253 if (next_cpu >= nr_cpu_ids) /* Shouldn't happen! */
254 goto disable;
255
256 cpumask_clear(current_mask);
257 cpumask_set_cpu(next_cpu, current_mask);
258
259 sched_setaffinity(0, current_mask);
260 return;
261
262 disable:
263 disable_migrate = true;
264}
265
214/*
215 * kthread_fn - The CPU time sampling/hardware latency detection kernel thread
216 *
217 * Used to periodically sample the CPU TSC via a call to get_sample. We
218 * disable interrupts, which does (intentionally) introduce latency since we
219 * need to ensure nothing else might be running (and thus preempting).
220 * Obviously this should never be used in production environments.
221 *
222 * Currently this runs on which ever CPU it was scheduled on, but most
223 * real-world hardware latency situations occur across several CPUs,
224 * but we might later generalize this if we find there are any actualy
225 * systems with alternate SMI delivery or other hardware latencies.
226 */
227static int kthread_fn(void *data)
228{
229 u64 interval;
230
231 while (!kthread_should_stop()) {
232
266/*
267 * kthread_fn - The CPU time sampling/hardware latency detection kernel thread
268 *
269 * Used to periodically sample the CPU TSC via a call to get_sample. We
270 * disable interrupts, which does (intentionally) introduce latency since we
271 * need to ensure nothing else might be running (and thus preempting).
272 * Obviously this should never be used in production environments.
273 *
274 * Currently this runs on which ever CPU it was scheduled on, but most
275 * real-world hardware latency situations occur across several CPUs,
276 * but we might later generalize this if we find there are any actualy
277 * systems with alternate SMI delivery or other hardware latencies.
278 */
279static int kthread_fn(void *data)
280{
281 u64 interval;
282
283 while (!kthread_should_stop()) {
284
285 move_to_next_cpu();
286
233 local_irq_disable();
234 get_sample();
235 local_irq_enable();
236
237 mutex_lock(&hwlat_data.lock);
238 interval = hwlat_data.sample_window - hwlat_data.sample_width;
239 mutex_unlock(&hwlat_data.lock);
240

--- 227 unchanged lines hidden (view full) ---

468static int hwlat_tracer_init(struct trace_array *tr)
469{
470 /* Only allow one instance to enable this */
471 if (hwlat_busy)
472 return -EBUSY;
473
474 hwlat_trace = tr;
475
287 local_irq_disable();
288 get_sample();
289 local_irq_enable();
290
291 mutex_lock(&hwlat_data.lock);
292 interval = hwlat_data.sample_window - hwlat_data.sample_width;
293 mutex_unlock(&hwlat_data.lock);
294

--- 227 unchanged lines hidden (view full) ---

522static int hwlat_tracer_init(struct trace_array *tr)
523{
524 /* Only allow one instance to enable this */
525 if (hwlat_busy)
526 return -EBUSY;
527
528 hwlat_trace = tr;
529
530 disable_migrate = false;
476 hwlat_data.count = 0;
477 tr->max_latency = 0;
478 save_tracing_thresh = tracing_thresh;
479
480 /* tracing_thresh is in nsecs, we speak in usecs */
481 if (!tracing_thresh)
482 tracing_thresh = last_tracing_thresh;
483

--- 44 unchanged lines hidden ---
531 hwlat_data.count = 0;
532 tr->max_latency = 0;
533 save_tracing_thresh = tracing_thresh;
534
535 /* tracing_thresh is in nsecs, we speak in usecs */
536 if (!tracing_thresh)
537 tracing_thresh = last_tracing_thresh;
538

--- 44 unchanged lines hidden ---