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(¶ms->common.threshold_actions); 1155d9af63eSTomas Glozar actions_init(¶ms->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(¶ms->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 ¶ms->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(¶ms->common.threshold_actions); 1935d9af63eSTomas Glozar actions_init(¶ms->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(¶ms->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 ¶ms->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(¶ms->common.threshold_actions); 2815d9af63eSTomas Glozar actions_init(¶ms->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(¶ms->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 ¶ms->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(¶ms->common.threshold_actions); 4045d9af63eSTomas Glozar actions_init(¶ms->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(¶ms->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 ¶ms->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