Skip to content

Commit 1f42835

Browse files
Daniel Bristot de Oliveirarostedt
authored andcommitted
rtla: Add hwnoise tool
The hwnoise tool is a special mode for the osnoise top tool. hwnoise dispatches the osnoise tracer and displays a summary of the noise. The difference is that it runs the tracer with the OSNOISE_IRQ_DISABLE option set, thus only allowing only hardware-related noise, resulting in a simplified output. hwnoise has the same features of osnoise. An example of the tool's output: # rtla hwnoise -c 1-11 -T 1 -d 10m -q Hardware-related Noise duration: 0 00:10:00 | time is in us CPU Period Runtime Noise % CPU Aval Max Noise Max Single HW NMI 1 #599 599000000 138 99.99997 3 3 4 74 2 #599 599000000 85 99.99998 3 3 4 75 3 #599 599000000 86 99.99998 4 3 6 75 4 #599 599000000 81 99.99998 4 4 2 75 5 #599 599000000 85 99.99998 2 2 2 75 Link: https://lkml.kernel.org/r/2d6f49a6f3a4f8b51b2c806458b1cff71ad4d014.1675805361.git.bristot@kernel.org Signed-off-by: Daniel Bristot de Oliveira <[email protected]> Cc: Daniel Bristot de Oliveira <[email protected]> Cc: Juri Lelli <[email protected]> Cc: Clark Williams <[email protected]> Cc: Bagas Sanjaya <[email protected]> Cc: Jonathan Corbet <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent ce6cc6f commit 1f42835

File tree

5 files changed

+198
-16
lines changed

5 files changed

+198
-16
lines changed

tools/tracing/rtla/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ install: doc_install
119119
$(STRIP) $(DESTDIR)$(BINDIR)/rtla
120120
@test ! -f $(DESTDIR)$(BINDIR)/osnoise || rm $(DESTDIR)$(BINDIR)/osnoise
121121
ln -s rtla $(DESTDIR)$(BINDIR)/osnoise
122+
@test ! -f $(DESTDIR)$(BINDIR)/hwnoise || rm $(DESTDIR)$(BINDIR)/hwnoise
123+
ln -s rtla $(DESTDIR)$(BINDIR)/hwnoise
122124
@test ! -f $(DESTDIR)$(BINDIR)/timerlat || rm $(DESTDIR)$(BINDIR)/timerlat
123125
ln -s rtla $(DESTDIR)$(BINDIR)/timerlat
124126

tools/tracing/rtla/src/osnoise.c

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,113 @@ void osnoise_put_tracing_thresh(struct osnoise_context *context)
734734
context->orig_tracing_thresh = OSNOISE_OPTION_INIT_VAL;
735735
}
736736

737+
static int osnoise_options_get_option(char *option)
738+
{
739+
char *options = tracefs_instance_file_read(NULL, "osnoise/options", NULL);
740+
char no_option[128];
741+
int retval = 0;
742+
char *opt;
743+
744+
if (!options)
745+
return OSNOISE_OPTION_INIT_VAL;
746+
747+
/*
748+
* Check first if the option is disabled.
749+
*/
750+
snprintf(no_option, sizeof(no_option), "NO_%s", option);
751+
752+
opt = strstr(options, no_option);
753+
if (opt)
754+
goto out_free;
755+
756+
/*
757+
* Now that it is not disabled, if the string is there, it is
758+
* enabled. If the string is not there, the option does not exist.
759+
*/
760+
opt = strstr(options, option);
761+
if (opt)
762+
retval = 1;
763+
else
764+
retval = OSNOISE_OPTION_INIT_VAL;
765+
766+
out_free:
767+
free(options);
768+
return retval;
769+
}
770+
771+
static int osnoise_options_set_option(char *option, bool onoff)
772+
{
773+
char no_option[128];
774+
775+
if (onoff)
776+
return tracefs_instance_file_write(NULL, "osnoise/options", option);
777+
778+
snprintf(no_option, sizeof(no_option), "NO_%s", option);
779+
780+
return tracefs_instance_file_write(NULL, "osnoise/options", no_option);
781+
}
782+
783+
static int osnoise_get_irq_disable(struct osnoise_context *context)
784+
{
785+
if (context->opt_irq_disable != OSNOISE_OPTION_INIT_VAL)
786+
return context->opt_irq_disable;
787+
788+
if (context->orig_opt_irq_disable != OSNOISE_OPTION_INIT_VAL)
789+
return context->orig_opt_irq_disable;
790+
791+
context->orig_opt_irq_disable = osnoise_options_get_option("OSNOISE_IRQ_DISABLE");
792+
793+
return context->orig_opt_irq_disable;
794+
}
795+
796+
int osnoise_set_irq_disable(struct osnoise_context *context, bool onoff)
797+
{
798+
int opt_irq_disable = osnoise_get_irq_disable(context);
799+
int retval;
800+
801+
if (opt_irq_disable == OSNOISE_OPTION_INIT_VAL)
802+
return -1;
803+
804+
if (opt_irq_disable == onoff)
805+
return 0;
806+
807+
retval = osnoise_options_set_option("OSNOISE_IRQ_DISABLE", onoff);
808+
if (retval < 0)
809+
return -1;
810+
811+
context->opt_irq_disable = onoff;
812+
813+
return 0;
814+
}
815+
816+
static void osnoise_restore_irq_disable(struct osnoise_context *context)
817+
{
818+
int retval;
819+
820+
if (context->orig_opt_irq_disable == OSNOISE_OPTION_INIT_VAL)
821+
return;
822+
823+
if (context->orig_opt_irq_disable == context->opt_irq_disable)
824+
goto out_done;
825+
826+
retval = osnoise_options_set_option("OSNOISE_IRQ_DISABLE", context->orig_opt_irq_disable);
827+
if (retval < 0)
828+
err_msg("Could not restore original OSNOISE_IRQ_DISABLE option\n");
829+
830+
out_done:
831+
context->orig_opt_irq_disable = OSNOISE_OPTION_INIT_VAL;
832+
}
833+
834+
static void osnoise_put_irq_disable(struct osnoise_context *context)
835+
{
836+
osnoise_restore_irq_disable(context);
837+
838+
if (context->orig_opt_irq_disable == OSNOISE_OPTION_INIT_VAL)
839+
return;
840+
841+
context->orig_opt_irq_disable = OSNOISE_OPTION_INIT_VAL;
842+
}
843+
737844
/*
738845
* enable_osnoise - enable osnoise tracer in the trace_instance
739846
*/
@@ -798,6 +905,9 @@ struct osnoise_context *osnoise_context_alloc(void)
798905
context->orig_tracing_thresh = OSNOISE_OPTION_INIT_VAL;
799906
context->tracing_thresh = OSNOISE_OPTION_INIT_VAL;
800907

908+
context->orig_opt_irq_disable = OSNOISE_OPTION_INIT_VAL;
909+
context->opt_irq_disable = OSNOISE_OPTION_INIT_VAL;
910+
801911
osnoise_get_context(context);
802912

803913
return context;
@@ -824,6 +934,7 @@ void osnoise_put_context(struct osnoise_context *context)
824934
osnoise_put_timerlat_period_us(context);
825935
osnoise_put_print_stack(context);
826936
osnoise_put_tracing_thresh(context);
937+
osnoise_put_irq_disable(context);
827938

828939
free(context);
829940
}
@@ -958,3 +1069,9 @@ int osnoise_main(int argc, char *argv[])
9581069
osnoise_usage(1);
9591070
exit(1);
9601071
}
1072+
1073+
int hwnoise_main(int argc, char *argv[])
1074+
{
1075+
osnoise_top_main(argc, argv);
1076+
exit(0);
1077+
}

tools/tracing/rtla/src/osnoise.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ struct osnoise_context {
3838
/* -1 as init value because 0 is disabled */
3939
long long orig_print_stack;
4040
long long print_stack;
41+
42+
/* -1 as init value because 0 is off */
43+
int orig_opt_irq_disable;
44+
int opt_irq_disable;
4145
};
4246

4347
/*
@@ -79,6 +83,8 @@ void osnoise_restore_print_stack(struct osnoise_context *context);
7983
int osnoise_set_print_stack(struct osnoise_context *context,
8084
long long print_stack);
8185

86+
int osnoise_set_irq_disable(struct osnoise_context *context, bool onoff);
87+
8288
/*
8389
* osnoise_tool - osnoise based tool definition.
8490
*/
@@ -97,3 +103,4 @@ struct osnoise_tool *osnoise_init_trace_tool(char *tracer);
97103
int osnoise_hist_main(int argc, char *argv[]);
98104
int osnoise_top_main(int argc, char **argv);
99105
int osnoise_main(int argc, char **argv);
106+
int hwnoise_main(int argc, char **argv);

tools/tracing/rtla/src/osnoise_top.c

Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
#include "osnoise.h"
1515
#include "utils.h"
1616

17+
enum osnoise_mode {
18+
MODE_OSNOISE = 0,
19+
MODE_HWNOISE
20+
};
21+
1722
/*
1823
* osnoise top parameters
1924
*/
@@ -32,6 +37,7 @@ struct osnoise_top_params {
3237
int set_sched;
3338
struct sched_attr sched_param;
3439
struct trace_events *events;
40+
enum osnoise_mode mode;
3541
};
3642

3743
struct osnoise_top_cpu {
@@ -143,15 +149,23 @@ osnoise_top_handler(struct trace_seq *s, struct tep_record *record,
143149
*/
144150
static void osnoise_top_header(struct osnoise_tool *top)
145151
{
152+
struct osnoise_top_params *params = top->params;
146153
struct trace_seq *s = top->trace.seq;
147154
char duration[26];
148155

149156
get_duration(top->start_time, duration, sizeof(duration));
150157

151158
trace_seq_printf(s, "\033[2;37;40m");
152-
trace_seq_printf(s, " Operating System Noise");
153-
trace_seq_printf(s, " ");
154-
trace_seq_printf(s, " ");
159+
trace_seq_printf(s, " ");
160+
161+
if (params->mode == MODE_OSNOISE) {
162+
trace_seq_printf(s, "Operating System Noise");
163+
trace_seq_printf(s, " ");
164+
} else if (params->mode == MODE_HWNOISE) {
165+
trace_seq_printf(s, "Hardware-related Noise");
166+
}
167+
168+
trace_seq_printf(s, " ");
155169
trace_seq_printf(s, "\033[0;0;0m");
156170
trace_seq_printf(s, "\n");
157171

@@ -162,7 +176,14 @@ static void osnoise_top_header(struct osnoise_tool *top)
162176
trace_seq_printf(s, " Noise ");
163177
trace_seq_printf(s, " %% CPU Aval ");
164178
trace_seq_printf(s, " Max Noise Max Single ");
165-
trace_seq_printf(s, " HW NMI IRQ Softirq Thread");
179+
trace_seq_printf(s, " HW NMI");
180+
181+
if (params->mode == MODE_HWNOISE)
182+
goto eol;
183+
184+
trace_seq_printf(s, " IRQ Softirq Thread");
185+
186+
eol:
166187
trace_seq_printf(s, "\033[0;0;0m");
167188
trace_seq_printf(s, "\n");
168189
}
@@ -181,6 +202,7 @@ static void clear_terminal(struct trace_seq *seq)
181202
*/
182203
static void osnoise_top_print(struct osnoise_tool *tool, int cpu)
183204
{
205+
struct osnoise_top_params *params = tool->params;
184206
struct trace_seq *s = tool->trace.seq;
185207
struct osnoise_top_cpu *cpu_data;
186208
struct osnoise_top_data *data;
@@ -205,6 +227,12 @@ static void osnoise_top_print(struct osnoise_tool *tool, int cpu)
205227

206228
trace_seq_printf(s, "%12llu ", cpu_data->hw_count);
207229
trace_seq_printf(s, "%12llu ", cpu_data->nmi_count);
230+
231+
if (params->mode == MODE_HWNOISE) {
232+
trace_seq_printf(s, "\n");
233+
return;
234+
}
235+
208236
trace_seq_printf(s, "%12llu ", cpu_data->irq_count);
209237
trace_seq_printf(s, "%12llu ", cpu_data->softirq_count);
210238
trace_seq_printf(s, "%12llu\n", cpu_data->thread_count);
@@ -241,12 +269,12 @@ osnoise_print_stats(struct osnoise_top_params *params, struct osnoise_tool *top)
241269
/*
242270
* osnoise_top_usage - prints osnoise top usage message
243271
*/
244-
void osnoise_top_usage(char *usage)
272+
static void osnoise_top_usage(struct osnoise_top_params *params, char *usage)
245273
{
246274
int i;
247275

248276
static const char * const msg[] = {
249-
" usage: rtla osnoise [top] [-h] [-q] [-D] [-d s] [-a us] [-p us] [-r us] [-s us] [-S us] \\",
277+
" [-h] [-q] [-D] [-d s] [-a us] [-p us] [-r us] [-s us] [-S us] \\",
250278
" [-T us] [-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] \\",
251279
" [-c cpu-list] [-P priority]",
252280
"",
@@ -277,9 +305,22 @@ void osnoise_top_usage(char *usage)
277305
if (usage)
278306
fprintf(stderr, "%s\n", usage);
279307

280-
fprintf(stderr, "rtla osnoise top: a per-cpu summary of the OS noise (version %s)\n",
308+
if (params->mode == MODE_OSNOISE) {
309+
fprintf(stderr,
310+
"rtla osnoise top: a per-cpu summary of the OS noise (version %s)\n",
281311
VERSION);
282312

313+
fprintf(stderr, " usage: rtla osnoise [top]");
314+
}
315+
316+
if (params->mode == MODE_HWNOISE) {
317+
fprintf(stderr,
318+
"rtla hwnoise: a summary of hardware-related noise (version %s)\n",
319+
VERSION);
320+
321+
fprintf(stderr, " usage: rtla hwnoise");
322+
}
323+
283324
for (i = 0; msg[i]; i++)
284325
fprintf(stderr, "%s\n", msg[i]);
285326
exit(1);
@@ -299,6 +340,9 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv)
299340
if (!params)
300341
exit(1);
301342

343+
if (strcmp(argv[0], "hwnoise") == 0)
344+
params->mode = MODE_HWNOISE;
345+
302346
while (1) {
303347
static struct option long_options[] = {
304348
{"auto", required_argument, 0, 'a'},
@@ -345,7 +389,7 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv)
345389
case 'c':
346390
retval = parse_cpu_list(optarg, &params->monitored_cpus);
347391
if (retval)
348-
osnoise_top_usage("\nInvalid -c cpu list\n");
392+
osnoise_top_usage(params, "\nInvalid -c cpu list\n");
349393
params->cpus = optarg;
350394
break;
351395
case 'D':
@@ -354,7 +398,7 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv)
354398
case 'd':
355399
params->duration = parse_seconds_duration(optarg);
356400
if (!params->duration)
357-
osnoise_top_usage("Invalid -D duration\n");
401+
osnoise_top_usage(params, "Invalid -D duration\n");
358402
break;
359403
case 'e':
360404
tevent = trace_event_alloc(optarg);
@@ -370,17 +414,17 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv)
370414
break;
371415
case 'h':
372416
case '?':
373-
osnoise_top_usage(NULL);
417+
osnoise_top_usage(params, NULL);
374418
break;
375419
case 'p':
376420
params->period = get_llong_from_str(optarg);
377421
if (params->period > 10000000)
378-
osnoise_top_usage("Period longer than 10 s\n");
422+
osnoise_top_usage(params, "Period longer than 10 s\n");
379423
break;
380424
case 'P':
381425
retval = parse_prio(optarg, &params->sched_param);
382426
if (retval == -1)
383-
osnoise_top_usage("Invalid -P priority");
427+
osnoise_top_usage(params, "Invalid -P priority");
384428
params->set_sched = 1;
385429
break;
386430
case 'q':
@@ -389,7 +433,7 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv)
389433
case 'r':
390434
params->runtime = get_llong_from_str(optarg);
391435
if (params->runtime < 100)
392-
osnoise_top_usage("Runtime shorter than 100 us\n");
436+
osnoise_top_usage(params, "Runtime shorter than 100 us\n");
393437
break;
394438
case 's':
395439
params->stop_us = get_llong_from_str(optarg);
@@ -415,7 +459,7 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv)
415459
exit(EXIT_FAILURE);
416460
}
417461
} else {
418-
osnoise_top_usage("--trigger requires a previous -e\n");
462+
osnoise_top_usage(params, "--trigger requires a previous -e\n");
419463
}
420464
break;
421465
case '1': /* filter */
@@ -426,11 +470,11 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv)
426470
exit(EXIT_FAILURE);
427471
}
428472
} else {
429-
osnoise_top_usage("--filter requires a previous -e\n");
473+
osnoise_top_usage(params, "--filter requires a previous -e\n");
430474
}
431475
break;
432476
default:
433-
osnoise_top_usage("Invalid option");
477+
osnoise_top_usage(params, "Invalid option");
434478
}
435479
}
436480

@@ -495,6 +539,14 @@ osnoise_top_apply_config(struct osnoise_tool *tool, struct osnoise_top_params *p
495539
}
496540
}
497541

542+
if (params->mode == MODE_HWNOISE) {
543+
retval = osnoise_set_irq_disable(tool->context, 1);
544+
if (retval) {
545+
err_msg("Failed to set OSNOISE_IRQ_DISABLE option\n");
546+
goto out_err;
547+
}
548+
}
549+
498550
return 0;
499551

500552
out_err:

0 commit comments

Comments
 (0)