xref: /linux/tools/tracing/rtla/src/cli.c (revision 9611c0ce215a66770ccbe5c126bf57ba8c31bcad)
15d9af63eSTomas Glozar // SPDX-License-Identifier: GPL-2.0
25d9af63eSTomas Glozar /*
35d9af63eSTomas Glozar  * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org>
45d9af63eSTomas Glozar  */
55d9af63eSTomas Glozar 
65d9af63eSTomas Glozar #define _GNU_SOURCE
75d9af63eSTomas Glozar #include <stdlib.h>
85d9af63eSTomas Glozar #include <string.h>
95d9af63eSTomas Glozar #include <stdio.h>
105d9af63eSTomas Glozar #include <unistd.h>
115d9af63eSTomas Glozar #include <sys/types.h>
125d9af63eSTomas Glozar 
135d9af63eSTomas Glozar #include <linux/compiler.h>
145d9af63eSTomas Glozar 
155d9af63eSTomas Glozar #define RTLA_ALLOW_CLI_P_H
165d9af63eSTomas Glozar #include "cli_p.h"
175d9af63eSTomas Glozar 
185d9af63eSTomas Glozar static const char * const osnoise_top_usage[] = {
195d9af63eSTomas Glozar 	"rtla osnoise [top] [<options>] [-h|--help]",
205d9af63eSTomas Glozar 	NULL,
215d9af63eSTomas Glozar };
225d9af63eSTomas Glozar 
235d9af63eSTomas Glozar static const char * const osnoise_hist_usage[] = {
245d9af63eSTomas Glozar 	"rtla osnoise hist [<options>] [-h|--help]",
255d9af63eSTomas Glozar 	NULL,
265d9af63eSTomas Glozar };
275d9af63eSTomas Glozar 
285d9af63eSTomas Glozar static const char * const timerlat_top_usage[] = {
295d9af63eSTomas Glozar 	"rtla timerlat [top] [<options>] [-h|--help]",
305d9af63eSTomas Glozar 	NULL,
315d9af63eSTomas Glozar };
325d9af63eSTomas Glozar 
335d9af63eSTomas Glozar static const char * const timerlat_hist_usage[] = {
345d9af63eSTomas Glozar 	"rtla timerlat hist [<options>] [-h|--help]",
355d9af63eSTomas Glozar 	NULL,
365d9af63eSTomas Glozar };
375d9af63eSTomas Glozar 
385d9af63eSTomas Glozar static const char * const hwnoise_usage[] = {
395d9af63eSTomas Glozar 	"rtla hwnoise [<options>] [-h|--help]",
405d9af63eSTomas Glozar 	NULL,
415d9af63eSTomas Glozar };
425d9af63eSTomas Glozar 
435d9af63eSTomas Glozar static const int common_parse_options_flags = PARSE_OPT_OPTARG_ALLOW_NEXT;
445d9af63eSTomas Glozar 
455d9af63eSTomas Glozar bool in_unit_test;
465d9af63eSTomas Glozar 
475d9af63eSTomas Glozar /*
485d9af63eSTomas Glozar  * osnoise_top_parse_args - allocs, parse and fill the cmd line parameters
495d9af63eSTomas Glozar  */
505d9af63eSTomas Glozar struct common_params *osnoise_top_parse_args(int argc, char **argv)
515d9af63eSTomas Glozar {
525d9af63eSTomas Glozar 	struct osnoise_params *params;
535d9af63eSTomas Glozar 	struct osnoise_cb_data cb_data;
545d9af63eSTomas Glozar 	const char * const *usage;
555d9af63eSTomas Glozar 
565d9af63eSTomas Glozar 	params = calloc_fatal(1, sizeof(*params));
575d9af63eSTomas Glozar 
585d9af63eSTomas Glozar 	cb_data.params = params;
595d9af63eSTomas Glozar 	cb_data.trace_output = NULL;
605d9af63eSTomas Glozar 
615d9af63eSTomas Glozar 	if (strcmp(argv[0], "hwnoise") == 0) {
625d9af63eSTomas Glozar 		params->mode = MODE_HWNOISE;
635d9af63eSTomas Glozar 		/*
645d9af63eSTomas Glozar 		 * Reduce CPU usage for 75% to avoid killing the system.
655d9af63eSTomas Glozar 		 */
665d9af63eSTomas Glozar 		params->runtime = 750000;
675d9af63eSTomas Glozar 		params->period = 1000000;
685d9af63eSTomas Glozar 		usage = hwnoise_usage;
695d9af63eSTomas Glozar 	} else {
705d9af63eSTomas Glozar 		usage = osnoise_top_usage;
715d9af63eSTomas Glozar 	}
725d9af63eSTomas Glozar 
735d9af63eSTomas Glozar 	const struct option osnoise_top_options[] = {
745d9af63eSTomas Glozar 	OPT_GROUP("Tracing Options:"),
755d9af63eSTomas Glozar 		OSNOISE_OPT_PERIOD,
765d9af63eSTomas Glozar 		OSNOISE_OPT_RUNTIME,
775d9af63eSTomas Glozar 		RTLA_OPT_STOP('s', "stop", "single sample"),
785d9af63eSTomas Glozar 		RTLA_OPT_STOP_TOTAL('S', "stop-total", "total sample"),
795d9af63eSTomas Glozar 		OSNOISE_OPT_THRESHOLD,
805d9af63eSTomas Glozar 		RTLA_OPT_TRACE_OUTPUT("osnoise", opt_osnoise_trace_output_cb),
815d9af63eSTomas Glozar 
825d9af63eSTomas Glozar 	OPT_GROUP("Event Configuration:"),
835d9af63eSTomas Glozar 		RTLA_OPT_EVENT,
845d9af63eSTomas Glozar 		RTLA_OPT_FILTER,
855d9af63eSTomas Glozar 		RTLA_OPT_TRIGGER,
865d9af63eSTomas Glozar 
875d9af63eSTomas Glozar 	OPT_GROUP("CPU Configuration:"),
885d9af63eSTomas Glozar 		RTLA_OPT_CPUS,
895d9af63eSTomas Glozar 		RTLA_OPT_HOUSEKEEPING,
905d9af63eSTomas Glozar 
915d9af63eSTomas Glozar 	OPT_GROUP("Thread Configuration:"),
925d9af63eSTomas Glozar 		RTLA_OPT_PRIORITY,
935d9af63eSTomas Glozar 		RTLA_OPT_CGROUP,
945d9af63eSTomas Glozar 
955d9af63eSTomas Glozar 	OPT_GROUP("Output:"),
965d9af63eSTomas Glozar 		RTLA_OPT_QUIET,
975d9af63eSTomas Glozar 
985d9af63eSTomas Glozar 	OPT_GROUP("System Tuning:"),
995d9af63eSTomas Glozar 		RTLA_OPT_TRACE_BUFFER_SIZE,
1005d9af63eSTomas Glozar 		RTLA_OPT_WARM_UP,
1015d9af63eSTomas Glozar 
1025d9af63eSTomas Glozar 	OPT_GROUP("Auto Analysis and Actions:"),
1035d9af63eSTomas Glozar 		RTLA_OPT_AUTO(opt_osnoise_auto_cb),
1045d9af63eSTomas Glozar 		RTLA_OPT_ON_THRESHOLD("stop-total", opt_osnoise_on_threshold_cb),
1055d9af63eSTomas Glozar 		RTLA_OPT_ON_END(opt_osnoise_on_end_cb),
1065d9af63eSTomas Glozar 
1075d9af63eSTomas Glozar 	OPT_GROUP("General:"),
1085d9af63eSTomas Glozar 		RTLA_OPT_DURATION,
1095d9af63eSTomas Glozar 		RTLA_OPT_DEBUG,
1105d9af63eSTomas Glozar 
1115d9af63eSTomas Glozar 	OPT_END(),
1125d9af63eSTomas Glozar 	};
1135d9af63eSTomas Glozar 
1145d9af63eSTomas Glozar 	actions_init(&params->common.threshold_actions);
1155d9af63eSTomas Glozar 	actions_init(&params->common.end_actions);
1165d9af63eSTomas Glozar 
1175d9af63eSTomas Glozar 	argc = parse_options(argc, (const char **)argv,
1185d9af63eSTomas Glozar 			     osnoise_top_options,
1195d9af63eSTomas Glozar 			     usage,
1205d9af63eSTomas Glozar 			     common_parse_options_flags);
1215d9af63eSTomas Glozar 	if (argc < 0)
1225d9af63eSTomas Glozar 		return NULL;
1235d9af63eSTomas Glozar 
1245d9af63eSTomas Glozar 	if (cb_data.trace_output)
1255d9af63eSTomas Glozar 		actions_add_trace_output(&params->common.threshold_actions, cb_data.trace_output);
1265d9af63eSTomas Glozar 
127244d0cbfSTomas Glozar 	if (geteuid() && !in_unit_test)
1285d9af63eSTomas Glozar 		fatal("osnoise needs root permission");
1295d9af63eSTomas Glozar 
1305d9af63eSTomas Glozar 	return &params->common;
1315d9af63eSTomas Glozar }
1325d9af63eSTomas Glozar 
1335d9af63eSTomas Glozar /*
1345d9af63eSTomas Glozar  * osnoise_hist_parse_args - allocs, parse and fill the cmd line parameters
1355d9af63eSTomas Glozar  */
1365d9af63eSTomas Glozar struct common_params *osnoise_hist_parse_args(int argc, char **argv)
1375d9af63eSTomas Glozar {
1385d9af63eSTomas Glozar 	struct osnoise_params *params;
1395d9af63eSTomas Glozar 	struct osnoise_cb_data cb_data;
1405d9af63eSTomas Glozar 
1415d9af63eSTomas Glozar 	params = calloc_fatal(1, sizeof(*params));
1425d9af63eSTomas Glozar 
1435d9af63eSTomas Glozar 	cb_data.params = params;
1445d9af63eSTomas Glozar 	cb_data.trace_output = NULL;
1455d9af63eSTomas Glozar 
1465d9af63eSTomas Glozar 	const struct option osnoise_hist_options[] = {
1475d9af63eSTomas Glozar 	OPT_GROUP("Tracing Options:"),
1485d9af63eSTomas Glozar 		OSNOISE_OPT_PERIOD,
1495d9af63eSTomas Glozar 		OSNOISE_OPT_RUNTIME,
1505d9af63eSTomas Glozar 		RTLA_OPT_STOP('s', "stop", "single sample"),
1515d9af63eSTomas Glozar 		RTLA_OPT_STOP_TOTAL('S', "stop-total", "total sample"),
1525d9af63eSTomas Glozar 		OSNOISE_OPT_THRESHOLD,
1535d9af63eSTomas Glozar 		RTLA_OPT_TRACE_OUTPUT("osnoise", opt_osnoise_trace_output_cb),
1545d9af63eSTomas Glozar 
1555d9af63eSTomas Glozar 	OPT_GROUP("Event Configuration:"),
1565d9af63eSTomas Glozar 		RTLA_OPT_EVENT,
1575d9af63eSTomas Glozar 		RTLA_OPT_FILTER,
1585d9af63eSTomas Glozar 		RTLA_OPT_TRIGGER,
1595d9af63eSTomas Glozar 
1605d9af63eSTomas Glozar 	OPT_GROUP("CPU Configuration:"),
1615d9af63eSTomas Glozar 		RTLA_OPT_CPUS,
1625d9af63eSTomas Glozar 		RTLA_OPT_HOUSEKEEPING,
1635d9af63eSTomas Glozar 
1645d9af63eSTomas Glozar 	OPT_GROUP("Thread Configuration:"),
1655d9af63eSTomas Glozar 		RTLA_OPT_PRIORITY,
1665d9af63eSTomas Glozar 		RTLA_OPT_CGROUP,
1675d9af63eSTomas Glozar 
1685d9af63eSTomas Glozar 	OPT_GROUP("Histogram Options:"),
1695d9af63eSTomas Glozar 		HIST_OPT_BUCKET_SIZE,
1705d9af63eSTomas Glozar 		HIST_OPT_ENTRIES,
1715d9af63eSTomas Glozar 		HIST_OPT_NO_HEADER,
1725d9af63eSTomas Glozar 		HIST_OPT_NO_SUMMARY,
1735d9af63eSTomas Glozar 		HIST_OPT_NO_INDEX,
1745d9af63eSTomas Glozar 		HIST_OPT_WITH_ZEROS,
1755d9af63eSTomas Glozar 
1765d9af63eSTomas Glozar 	OPT_GROUP("System Tuning:"),
1775d9af63eSTomas Glozar 		RTLA_OPT_TRACE_BUFFER_SIZE,
1785d9af63eSTomas Glozar 		RTLA_OPT_WARM_UP,
1795d9af63eSTomas Glozar 
1805d9af63eSTomas Glozar 	OPT_GROUP("Auto Analysis and Actions:"),
1815d9af63eSTomas Glozar 		RTLA_OPT_AUTO(opt_osnoise_auto_cb),
1825d9af63eSTomas Glozar 		RTLA_OPT_ON_THRESHOLD("stop-total", opt_osnoise_on_threshold_cb),
1835d9af63eSTomas Glozar 		RTLA_OPT_ON_END(opt_osnoise_on_end_cb),
1845d9af63eSTomas Glozar 
1855d9af63eSTomas Glozar 	OPT_GROUP("General:"),
1865d9af63eSTomas Glozar 		RTLA_OPT_DURATION,
1875d9af63eSTomas Glozar 		RTLA_OPT_DEBUG,
1885d9af63eSTomas Glozar 
1895d9af63eSTomas Glozar 	OPT_END(),
1905d9af63eSTomas Glozar 	};
1915d9af63eSTomas Glozar 
1925d9af63eSTomas Glozar 	actions_init(&params->common.threshold_actions);
1935d9af63eSTomas Glozar 	actions_init(&params->common.end_actions);
1945d9af63eSTomas Glozar 
1955d9af63eSTomas Glozar 	/* display data in microseconds */
1965d9af63eSTomas Glozar 	params->common.output_divisor = 1000;
1975d9af63eSTomas Glozar 	params->common.hist.bucket_size = 1;
1985d9af63eSTomas Glozar 	params->common.hist.entries = 256;
1995d9af63eSTomas Glozar 
2005d9af63eSTomas Glozar 	argc = parse_options(argc, (const char **)argv,
2015d9af63eSTomas Glozar 			     osnoise_hist_options, osnoise_hist_usage,
2025d9af63eSTomas Glozar 			     common_parse_options_flags);
2035d9af63eSTomas Glozar 	if (argc < 0)
2045d9af63eSTomas Glozar 		return NULL;
2055d9af63eSTomas Glozar 
2065d9af63eSTomas Glozar 	if (cb_data.trace_output)
2075d9af63eSTomas Glozar 		actions_add_trace_output(&params->common.threshold_actions, cb_data.trace_output);
2085d9af63eSTomas Glozar 
209244d0cbfSTomas Glozar 	if (geteuid() && !in_unit_test)
2105d9af63eSTomas Glozar 		fatal("rtla needs root permission");
2115d9af63eSTomas Glozar 
2125d9af63eSTomas Glozar 	if (params->common.hist.no_index && !params->common.hist.with_zeros)
2135d9af63eSTomas Glozar 		fatal("no-index set and with-zeros not set - it does not make sense");
2145d9af63eSTomas Glozar 
2155d9af63eSTomas Glozar 	return &params->common;
2165d9af63eSTomas Glozar }
2175d9af63eSTomas Glozar 
2185d9af63eSTomas Glozar struct common_params *timerlat_top_parse_args(int argc, char **argv)
2195d9af63eSTomas Glozar {
2205d9af63eSTomas Glozar 	struct timerlat_params *params;
2215d9af63eSTomas Glozar 	struct timerlat_cb_data cb_data;
2225d9af63eSTomas Glozar 
2235d9af63eSTomas Glozar 	params = calloc_fatal(1, sizeof(*params));
2245d9af63eSTomas Glozar 
2255d9af63eSTomas Glozar 	cb_data.params = params;
2265d9af63eSTomas Glozar 	cb_data.trace_output = NULL;
2275d9af63eSTomas Glozar 
2285d9af63eSTomas Glozar 	const struct option timerlat_top_options[] = {
2295d9af63eSTomas Glozar 	OPT_GROUP("Tracing Options:"),
2305d9af63eSTomas Glozar 		TIMERLAT_OPT_PERIOD,
2315d9af63eSTomas Glozar 		RTLA_OPT_STOP('i', "irq", "irq latency"),
2325d9af63eSTomas Glozar 		RTLA_OPT_STOP_TOTAL('T', "thread", "thread latency"),
2335d9af63eSTomas Glozar 		TIMERLAT_OPT_STACK,
2345d9af63eSTomas Glozar 		RTLA_OPT_TRACE_OUTPUT("timerlat", opt_timerlat_trace_output_cb),
2355d9af63eSTomas Glozar 
2365d9af63eSTomas Glozar 	OPT_GROUP("Event Configuration:"),
2375d9af63eSTomas Glozar 		RTLA_OPT_EVENT,
2385d9af63eSTomas Glozar 		RTLA_OPT_FILTER,
2395d9af63eSTomas Glozar 		RTLA_OPT_TRIGGER,
2405d9af63eSTomas Glozar 
2415d9af63eSTomas Glozar 	OPT_GROUP("CPU Configuration:"),
2425d9af63eSTomas Glozar 		RTLA_OPT_CPUS,
2435d9af63eSTomas Glozar 		RTLA_OPT_HOUSEKEEPING,
2445d9af63eSTomas Glozar 
2455d9af63eSTomas Glozar 	OPT_GROUP("Thread Configuration:"),
2465d9af63eSTomas Glozar 		RTLA_OPT_PRIORITY,
2475d9af63eSTomas Glozar 		RTLA_OPT_CGROUP,
2485d9af63eSTomas Glozar 		RTLA_OPT_USER_THREADS,
2495d9af63eSTomas Glozar 		RTLA_OPT_KERNEL_THREADS,
2505d9af63eSTomas Glozar 		RTLA_OPT_USER_LOAD,
251*03d745b9STomas Glozar 		TIMERLAT_OPT_ALIGNED,
2525d9af63eSTomas Glozar 
2535d9af63eSTomas Glozar 	OPT_GROUP("Output:"),
2545d9af63eSTomas Glozar 		TIMERLAT_OPT_NANO,
2555d9af63eSTomas Glozar 		RTLA_OPT_QUIET,
2565d9af63eSTomas Glozar 
2575d9af63eSTomas Glozar 	OPT_GROUP("System Tuning:"),
2585d9af63eSTomas Glozar 		TIMERLAT_OPT_DMA_LATENCY,
2595d9af63eSTomas Glozar 		TIMERLAT_OPT_DEEPEST_IDLE_STATE,
2605d9af63eSTomas Glozar 		RTLA_OPT_TRACE_BUFFER_SIZE,
2615d9af63eSTomas Glozar 		RTLA_OPT_WARM_UP,
2625d9af63eSTomas Glozar 
2635d9af63eSTomas Glozar 	OPT_GROUP("Auto Analysis and Actions:"),
2645d9af63eSTomas Glozar 		RTLA_OPT_AUTO(opt_timerlat_auto_cb),
2655d9af63eSTomas Glozar 		TIMERLAT_OPT_AA_ONLY,
2665d9af63eSTomas Glozar 		TIMERLAT_OPT_NO_AA,
2675d9af63eSTomas Glozar 		TIMERLAT_OPT_DUMPS_TASKS,
2685d9af63eSTomas Glozar 		RTLA_OPT_ON_THRESHOLD("latency", opt_timerlat_on_threshold_cb),
2695d9af63eSTomas Glozar 		RTLA_OPT_ON_END(opt_timerlat_on_end_cb),
2705d9af63eSTomas Glozar 		TIMERLAT_OPT_BPF_ACTION,
2715d9af63eSTomas Glozar 		TIMERLAT_OPT_STACK_FORMAT,
2725d9af63eSTomas Glozar 
2735d9af63eSTomas Glozar 	OPT_GROUP("General:"),
2745d9af63eSTomas Glozar 		RTLA_OPT_DURATION,
2755d9af63eSTomas Glozar 		RTLA_OPT_DEBUG,
2765d9af63eSTomas Glozar 
2775d9af63eSTomas Glozar 	OPT_END(),
2785d9af63eSTomas Glozar 	};
2795d9af63eSTomas Glozar 
2805d9af63eSTomas Glozar 	actions_init(&params->common.threshold_actions);
2815d9af63eSTomas Glozar 	actions_init(&params->common.end_actions);
2825d9af63eSTomas Glozar 
2835d9af63eSTomas Glozar 	/* disabled by default */
2845d9af63eSTomas Glozar 	params->dma_latency = -1;
2855d9af63eSTomas Glozar 	params->deepest_idle_state = -2;
2865d9af63eSTomas Glozar 
2875d9af63eSTomas Glozar 	/* display data in microseconds */
2885d9af63eSTomas Glozar 	params->common.output_divisor = 1000;
2895d9af63eSTomas Glozar 
2905d9af63eSTomas Glozar 	/* default to BPF mode */
2915d9af63eSTomas Glozar 	params->mode = TRACING_MODE_BPF;
2925d9af63eSTomas Glozar 
2935d9af63eSTomas Glozar 	/* default to truncate stack format */
2945d9af63eSTomas Glozar 	params->stack_format = STACK_FORMAT_TRUNCATE;
2955d9af63eSTomas Glozar 
2965d9af63eSTomas Glozar 	argc = parse_options(argc, (const char **)argv,
2975d9af63eSTomas Glozar 			     timerlat_top_options, timerlat_top_usage,
2985d9af63eSTomas Glozar 			     common_parse_options_flags);
2995d9af63eSTomas Glozar 	if (argc < 0)
3005d9af63eSTomas Glozar 		return NULL;
3015d9af63eSTomas Glozar 
3025d9af63eSTomas Glozar 	if (cb_data.trace_output)
3035d9af63eSTomas Glozar 		actions_add_trace_output(&params->common.threshold_actions, cb_data.trace_output);
3045d9af63eSTomas Glozar 
305244d0cbfSTomas Glozar 	if (geteuid() && !in_unit_test)
3065d9af63eSTomas Glozar 		fatal("rtla needs root permission");
3075d9af63eSTomas Glozar 
3085d9af63eSTomas Glozar 	/*
3095d9af63eSTomas Glozar 	 * Auto analysis only happens if stop tracing, thus:
3105d9af63eSTomas Glozar 	 */
3115d9af63eSTomas Glozar 	if (!params->common.stop_us && !params->common.stop_total_us)
3125d9af63eSTomas Glozar 		params->no_aa = 1;
3135d9af63eSTomas Glozar 
3145d9af63eSTomas Glozar 	if (params->no_aa && params->common.aa_only)
3155d9af63eSTomas Glozar 		fatal("--no-aa and --aa-only are mutually exclusive!");
3165d9af63eSTomas Glozar 
3175d9af63eSTomas Glozar 	if (params->common.kernel_workload && params->common.user_workload)
3185d9af63eSTomas Glozar 		fatal("--kernel-threads and --user-threads are mutually exclusive!");
3195d9af63eSTomas Glozar 
3205d9af63eSTomas Glozar 	/*
3215d9af63eSTomas Glozar 	 * If auto-analysis or trace output is enabled, switch from BPF mode to
3225d9af63eSTomas Glozar 	 * mixed mode
3235d9af63eSTomas Glozar 	 */
3245d9af63eSTomas Glozar 	if (params->mode == TRACING_MODE_BPF &&
3255d9af63eSTomas Glozar 		(params->common.threshold_actions.present[ACTION_TRACE_OUTPUT] ||
3265d9af63eSTomas Glozar 		params->common.end_actions.present[ACTION_TRACE_OUTPUT] ||
3275d9af63eSTomas Glozar 		!params->no_aa))
3285d9af63eSTomas Glozar 		params->mode = TRACING_MODE_MIXED;
3295d9af63eSTomas Glozar 
3305d9af63eSTomas Glozar 	return &params->common;
3315d9af63eSTomas Glozar }
3325d9af63eSTomas Glozar 
3335d9af63eSTomas Glozar struct common_params *timerlat_hist_parse_args(int argc, char **argv)
3345d9af63eSTomas Glozar {
3355d9af63eSTomas Glozar 	struct timerlat_params *params;
3365d9af63eSTomas Glozar 	struct timerlat_cb_data cb_data;
3375d9af63eSTomas Glozar 
3385d9af63eSTomas Glozar 	params = calloc_fatal(1, sizeof(*params));
3395d9af63eSTomas Glozar 
3405d9af63eSTomas Glozar 	cb_data.params = params;
3415d9af63eSTomas Glozar 	cb_data.trace_output = NULL;
3425d9af63eSTomas Glozar 
3435d9af63eSTomas Glozar 	const struct option timerlat_hist_options[] = {
3445d9af63eSTomas Glozar 	OPT_GROUP("Tracing Options:"),
3455d9af63eSTomas Glozar 		TIMERLAT_OPT_PERIOD,
3465d9af63eSTomas Glozar 		RTLA_OPT_STOP('i', "irq", "irq latency"),
3475d9af63eSTomas Glozar 		RTLA_OPT_STOP_TOTAL('T', "thread", "thread latency"),
3485d9af63eSTomas Glozar 		TIMERLAT_OPT_STACK,
3495d9af63eSTomas Glozar 		RTLA_OPT_TRACE_OUTPUT("timerlat", opt_timerlat_trace_output_cb),
3505d9af63eSTomas Glozar 
3515d9af63eSTomas Glozar 	OPT_GROUP("Event Configuration:"),
3525d9af63eSTomas Glozar 		RTLA_OPT_EVENT,
3535d9af63eSTomas Glozar 		RTLA_OPT_FILTER,
3545d9af63eSTomas Glozar 		RTLA_OPT_TRIGGER,
3555d9af63eSTomas Glozar 
3565d9af63eSTomas Glozar 	OPT_GROUP("CPU Configuration:"),
3575d9af63eSTomas Glozar 		RTLA_OPT_CPUS,
3585d9af63eSTomas Glozar 		RTLA_OPT_HOUSEKEEPING,
3595d9af63eSTomas Glozar 
3605d9af63eSTomas Glozar 	OPT_GROUP("Thread Configuration:"),
3615d9af63eSTomas Glozar 		RTLA_OPT_PRIORITY,
3625d9af63eSTomas Glozar 		RTLA_OPT_CGROUP,
3635d9af63eSTomas Glozar 		RTLA_OPT_USER_THREADS,
3645d9af63eSTomas Glozar 		RTLA_OPT_KERNEL_THREADS,
3655d9af63eSTomas Glozar 		RTLA_OPT_USER_LOAD,
366*03d745b9STomas Glozar 		TIMERLAT_OPT_ALIGNED,
3675d9af63eSTomas Glozar 
3685d9af63eSTomas Glozar 	OPT_GROUP("Histogram Options:"),
3695d9af63eSTomas Glozar 		HIST_OPT_BUCKET_SIZE,
3705d9af63eSTomas Glozar 		HIST_OPT_ENTRIES,
3715d9af63eSTomas Glozar 		HIST_OPT_NO_IRQ,
3725d9af63eSTomas Glozar 		HIST_OPT_NO_THREAD,
3735d9af63eSTomas Glozar 		HIST_OPT_NO_HEADER,
3745d9af63eSTomas Glozar 		HIST_OPT_NO_SUMMARY,
3755d9af63eSTomas Glozar 		HIST_OPT_NO_INDEX,
3765d9af63eSTomas Glozar 		HIST_OPT_WITH_ZEROS,
3775d9af63eSTomas Glozar 
3785d9af63eSTomas Glozar 	OPT_GROUP("Output:"),
3795d9af63eSTomas Glozar 		TIMERLAT_OPT_NANO,
3805d9af63eSTomas Glozar 
3815d9af63eSTomas Glozar 	OPT_GROUP("System Tuning:"),
3825d9af63eSTomas Glozar 		TIMERLAT_OPT_DMA_LATENCY,
3835d9af63eSTomas Glozar 		TIMERLAT_OPT_DEEPEST_IDLE_STATE,
3845d9af63eSTomas Glozar 		RTLA_OPT_TRACE_BUFFER_SIZE,
3855d9af63eSTomas Glozar 		RTLA_OPT_WARM_UP,
3865d9af63eSTomas Glozar 
3875d9af63eSTomas Glozar 	OPT_GROUP("Auto Analysis and Actions:"),
3885d9af63eSTomas Glozar 		RTLA_OPT_AUTO(opt_timerlat_auto_cb),
3895d9af63eSTomas Glozar 		TIMERLAT_OPT_NO_AA,
3905d9af63eSTomas Glozar 		TIMERLAT_OPT_DUMPS_TASKS,
3915d9af63eSTomas Glozar 		RTLA_OPT_ON_THRESHOLD("latency", opt_timerlat_on_threshold_cb),
3925d9af63eSTomas Glozar 		RTLA_OPT_ON_END(opt_timerlat_on_end_cb),
3935d9af63eSTomas Glozar 		TIMERLAT_OPT_BPF_ACTION,
3945d9af63eSTomas Glozar 		TIMERLAT_OPT_STACK_FORMAT,
3955d9af63eSTomas Glozar 
3965d9af63eSTomas Glozar 	OPT_GROUP("General:"),
3975d9af63eSTomas Glozar 		RTLA_OPT_DURATION,
3985d9af63eSTomas Glozar 		RTLA_OPT_DEBUG,
3995d9af63eSTomas Glozar 
4005d9af63eSTomas Glozar 	OPT_END(),
4015d9af63eSTomas Glozar 	};
4025d9af63eSTomas Glozar 
4035d9af63eSTomas Glozar 	actions_init(&params->common.threshold_actions);
4045d9af63eSTomas Glozar 	actions_init(&params->common.end_actions);
4055d9af63eSTomas Glozar 
4065d9af63eSTomas Glozar 	/* disabled by default */
4075d9af63eSTomas Glozar 	params->dma_latency = -1;
4085d9af63eSTomas Glozar 
4095d9af63eSTomas Glozar 	/* disabled by default */
4105d9af63eSTomas Glozar 	params->deepest_idle_state = -2;
4115d9af63eSTomas Glozar 
4125d9af63eSTomas Glozar 	/* display data in microseconds */
4135d9af63eSTomas Glozar 	params->common.output_divisor = 1000;
4145d9af63eSTomas Glozar 	params->common.hist.bucket_size = 1;
4155d9af63eSTomas Glozar 	params->common.hist.entries = 256;
4165d9af63eSTomas Glozar 
4175d9af63eSTomas Glozar 	/* default to BPF mode */
4185d9af63eSTomas Glozar 	params->mode = TRACING_MODE_BPF;
4195d9af63eSTomas Glozar 
4205d9af63eSTomas Glozar 	/* default to truncate stack format */
4215d9af63eSTomas Glozar 	params->stack_format = STACK_FORMAT_TRUNCATE;
4225d9af63eSTomas Glozar 
4235d9af63eSTomas Glozar 	argc = parse_options(argc, (const char **)argv,
4245d9af63eSTomas Glozar 			     timerlat_hist_options, timerlat_hist_usage,
4255d9af63eSTomas Glozar 			     common_parse_options_flags);
4265d9af63eSTomas Glozar 	if (argc < 0)
4275d9af63eSTomas Glozar 		return NULL;
4285d9af63eSTomas Glozar 
4295d9af63eSTomas Glozar 	if (cb_data.trace_output)
4305d9af63eSTomas Glozar 		actions_add_trace_output(&params->common.threshold_actions, cb_data.trace_output);
4315d9af63eSTomas Glozar 
432244d0cbfSTomas Glozar 	if (geteuid() && !in_unit_test)
4335d9af63eSTomas Glozar 		fatal("rtla needs root permission");
4345d9af63eSTomas Glozar 
4355d9af63eSTomas Glozar 	if (params->common.hist.no_irq && params->common.hist.no_thread)
4365d9af63eSTomas Glozar 		fatal("no-irq and no-thread set, there is nothing to do here");
4375d9af63eSTomas Glozar 
4385d9af63eSTomas Glozar 	if (params->common.hist.no_index && !params->common.hist.with_zeros)
4395d9af63eSTomas Glozar 		fatal("no-index set with with-zeros is not set - it does not make sense");
4405d9af63eSTomas Glozar 
4415d9af63eSTomas Glozar 	/*
4425d9af63eSTomas Glozar 	 * Auto analysis only happens if stop tracing, thus:
4435d9af63eSTomas Glozar 	 */
4445d9af63eSTomas Glozar 	if (!params->common.stop_us && !params->common.stop_total_us)
4455d9af63eSTomas Glozar 		params->no_aa = 1;
4465d9af63eSTomas Glozar 
4475d9af63eSTomas Glozar 	if (params->common.kernel_workload && params->common.user_workload)
4485d9af63eSTomas Glozar 		fatal("--kernel-threads and --user-threads are mutually exclusive!");
4495d9af63eSTomas Glozar 
4505d9af63eSTomas Glozar 	/*
4515d9af63eSTomas Glozar 	 * If auto-analysis or trace output is enabled, switch from BPF mode to
4525d9af63eSTomas Glozar 	 * mixed mode
4535d9af63eSTomas Glozar 	 */
4545d9af63eSTomas Glozar 	if (params->mode == TRACING_MODE_BPF &&
4555d9af63eSTomas Glozar 		(params->common.threshold_actions.present[ACTION_TRACE_OUTPUT] ||
4565d9af63eSTomas Glozar 		params->common.end_actions.present[ACTION_TRACE_OUTPUT] ||
4575d9af63eSTomas Glozar 		!params->no_aa))
4585d9af63eSTomas Glozar 		params->mode = TRACING_MODE_MIXED;
4595d9af63eSTomas Glozar 
4605d9af63eSTomas Glozar 	return &params->common;
4615d9af63eSTomas Glozar }
4625d9af63eSTomas Glozar 
4635d9af63eSTomas Glozar /*
4645d9af63eSTomas Glozar  * rtla_usage - print rtla usage
4655d9af63eSTomas Glozar  */
4665d9af63eSTomas Glozar __noreturn static void rtla_usage(int err)
4675d9af63eSTomas Glozar {
4685d9af63eSTomas Glozar 	int i;
4695d9af63eSTomas Glozar 
4705d9af63eSTomas Glozar 	static const char * const msg[] = {
4715d9af63eSTomas Glozar 		"",
4725d9af63eSTomas Glozar 		"rtla version " VERSION,
4735d9af63eSTomas Glozar 		"",
4745d9af63eSTomas Glozar 		"  usage: rtla COMMAND ...",
4755d9af63eSTomas Glozar 		"",
4765d9af63eSTomas Glozar 		"  commands:",
4775d9af63eSTomas Glozar 		"     osnoise  - gives information about the operating system noise (osnoise)",
4785d9af63eSTomas Glozar 		"     hwnoise  - gives information about hardware-related noise",
4795d9af63eSTomas Glozar 		"     timerlat - measures the timer irq and thread latency",
4805d9af63eSTomas Glozar 		"",
4815d9af63eSTomas Glozar 		NULL,
4825d9af63eSTomas Glozar 	};
4835d9af63eSTomas Glozar 
4845d9af63eSTomas Glozar 	for (i = 0; msg[i]; i++)
4855d9af63eSTomas Glozar 		fprintf(stderr, "%s\n", msg[i]);
4865d9af63eSTomas Glozar 	exit(err);
4875d9af63eSTomas Glozar }
4885d9af63eSTomas Glozar 
4895d9af63eSTomas Glozar /*
4905d9af63eSTomas Glozar  * run_tool_command - try to run a rtla tool command
4915d9af63eSTomas Glozar  *
4925d9af63eSTomas Glozar  * It returns 0 if it fails. The tool's main will generally not
4935d9af63eSTomas Glozar  * return as they should call exit().
4945d9af63eSTomas Glozar  */
4955d9af63eSTomas Glozar int run_tool_command(int argc, char **argv, int start_position)
4965d9af63eSTomas Glozar {
4975d9af63eSTomas Glozar 	if (strcmp(argv[start_position], "osnoise") == 0) {
4985d9af63eSTomas Glozar 		osnoise_main(argc-start_position, &argv[start_position]);
4995d9af63eSTomas Glozar 		goto ran;
5005d9af63eSTomas Glozar 	} else if (strcmp(argv[start_position], "hwnoise") == 0) {
5015d9af63eSTomas Glozar 		hwnoise_main(argc-start_position, &argv[start_position]);
5025d9af63eSTomas Glozar 		goto ran;
5035d9af63eSTomas Glozar 	} else if (strcmp(argv[start_position], "timerlat") == 0) {
5045d9af63eSTomas Glozar 		timerlat_main(argc-start_position, &argv[start_position]);
5055d9af63eSTomas Glozar 		goto ran;
5065d9af63eSTomas Glozar 	}
5075d9af63eSTomas Glozar 
5085d9af63eSTomas Glozar 	return 0;
5095d9af63eSTomas Glozar ran:
5105d9af63eSTomas Glozar 	return 1;
5115d9af63eSTomas Glozar }
5125d9af63eSTomas Glozar 
5135d9af63eSTomas Glozar /* Set main as weak to allow overriding it for building unit test binary */
5145d9af63eSTomas Glozar #pragma weak main
5155d9af63eSTomas Glozar 
5165d9af63eSTomas Glozar int main(int argc, char *argv[])
5175d9af63eSTomas Glozar {
5185d9af63eSTomas Glozar 	int retval;
5195d9af63eSTomas Glozar 
5205d9af63eSTomas Glozar 	/* is it an alias? */
5215d9af63eSTomas Glozar 	retval = run_tool_command(argc, argv, 0);
5225d9af63eSTomas Glozar 	if (retval)
5235d9af63eSTomas Glozar 		exit(0);
5245d9af63eSTomas Glozar 
5255d9af63eSTomas Glozar 	if (argc < 2)
5265d9af63eSTomas Glozar 		goto usage;
5275d9af63eSTomas Glozar 
5285d9af63eSTomas Glozar 	if (strcmp(argv[1], "-h") == 0)
5295d9af63eSTomas Glozar 		rtla_usage(129);
5305d9af63eSTomas Glozar 	else if (strcmp(argv[1], "--help") == 0)
5315d9af63eSTomas Glozar 		rtla_usage(129);
5325d9af63eSTomas Glozar 
5335d9af63eSTomas Glozar 	retval = run_tool_command(argc, argv, 1);
5345d9af63eSTomas Glozar 	if (retval)
5355d9af63eSTomas Glozar 		exit(0);
5365d9af63eSTomas Glozar 
5375d9af63eSTomas Glozar usage:
5385d9af63eSTomas Glozar 	rtla_usage(129);
5395d9af63eSTomas Glozar }
540