linux/tools/power/cpupower/utils/cpupower.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  (C) 2010,2011       Thomas Renninger <trenn@suse.de>, Novell Inc.
   4 *
   5 *  Ideas taken over from the perf userspace tool (included in the Linus
   6 *  kernel git repo): subcommand builtins and param parsing.
   7 */
   8
   9#include <stdio.h>
  10#include <stdlib.h>
  11#include <string.h>
  12#include <unistd.h>
  13#include <errno.h>
  14#include <sched.h>
  15#include <sys/types.h>
  16#include <sys/stat.h>
  17#include <sys/utsname.h>
  18
  19#include "builtin.h"
  20#include "helpers/helpers.h"
  21#include "helpers/bitmask.h"
  22
  23#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
  24
  25static int cmd_help(int argc, const char **argv);
  26
  27/* Global cpu_info object available for all binaries
  28 * Info only retrieved from CPU 0
  29 *
  30 * Values will be zero/unknown on non X86 archs
  31 */
  32struct cpupower_cpu_info cpupower_cpu_info;
  33int run_as_root;
  34int base_cpu;
  35/* Affected cpus chosen by -c/--cpu param */
  36struct bitmask *cpus_chosen;
  37struct bitmask *online_cpus;
  38struct bitmask *offline_cpus;
  39
  40#ifdef DEBUG
  41int be_verbose;
  42#endif
  43
  44static void print_help(void);
  45
  46struct cmd_struct {
  47        const char *cmd;
  48        int (*main)(int, const char **);
  49        int needs_root;
  50};
  51
  52static struct cmd_struct commands[] = {
  53        { "frequency-info",     cmd_freq_info,  0       },
  54        { "frequency-set",      cmd_freq_set,   1       },
  55        { "idle-info",          cmd_idle_info,  0       },
  56        { "idle-set",           cmd_idle_set,   1       },
  57        { "set",                cmd_set,        1       },
  58        { "info",               cmd_info,       0       },
  59        { "monitor",            cmd_monitor,    0       },
  60        { "help",               cmd_help,       0       },
  61        /*      { "bench",      cmd_bench,      1       }, */
  62};
  63
  64static void print_help(void)
  65{
  66        unsigned int i;
  67
  68#ifdef DEBUG
  69        printf(_("Usage:\tcpupower [-d|--debug] [-c|--cpu cpulist ] <command> [<args>]\n"));
  70#else
  71        printf(_("Usage:\tcpupower [-c|--cpu cpulist ] <command> [<args>]\n"));
  72#endif
  73        printf(_("Supported commands are:\n"));
  74        for (i = 0; i < ARRAY_SIZE(commands); i++)
  75                printf("\t%s\n", commands[i].cmd);
  76        printf(_("\nNot all commands can make use of the -c cpulist option.\n"));
  77        printf(_("\nUse 'cpupower help <command>' for getting help for above commands.\n"));
  78}
  79
  80static int print_man_page(const char *subpage)
  81{
  82        int len;
  83        char *page;
  84
  85        len = 10; /* enough for "cpupower-" */
  86        if (subpage != NULL)
  87                len += strlen(subpage);
  88
  89        page = malloc(len);
  90        if (!page)
  91                return -ENOMEM;
  92
  93        sprintf(page, "cpupower");
  94        if ((subpage != NULL) && strcmp(subpage, "help")) {
  95                strcat(page, "-");
  96                strcat(page, subpage);
  97        }
  98
  99        execlp("man", "man", page, NULL);
 100
 101        /* should not be reached */
 102        return -EINVAL;
 103}
 104
 105static int cmd_help(int argc, const char **argv)
 106{
 107        if (argc > 1) {
 108                print_man_page(argv[1]); /* exits within execlp() */
 109                return EXIT_FAILURE;
 110        }
 111
 112        print_help();
 113        return EXIT_SUCCESS;
 114}
 115
 116static void print_version(void)
 117{
 118        printf(PACKAGE " " VERSION "\n");
 119        printf(_("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT);
 120}
 121
 122static void handle_options(int *argc, const char ***argv)
 123{
 124        int ret, x, new_argc = 0;
 125
 126        if (*argc < 1)
 127                return;
 128
 129        for (x = 0;  x < *argc && ((*argv)[x])[0] == '-'; x++) {
 130                const char *param = (*argv)[x];
 131                if (!strcmp(param, "-h") || !strcmp(param, "--help")) {
 132                        print_help();
 133                        exit(EXIT_SUCCESS);
 134                } else if (!strcmp(param, "-c") || !strcmp(param, "--cpu")) {
 135                        if (*argc < 2) {
 136                                print_help();
 137                                exit(EXIT_FAILURE);
 138                        }
 139                        if (!strcmp((*argv)[x+1], "all"))
 140                                bitmask_setall(cpus_chosen);
 141                        else {
 142                                ret = bitmask_parselist(
 143                                                (*argv)[x+1], cpus_chosen);
 144                                if (ret < 0) {
 145                                        fprintf(stderr, _("Error parsing cpu "
 146                                                          "list\n"));
 147                                        exit(EXIT_FAILURE);
 148                                }
 149                        }
 150                        x += 1;
 151                        /* Cut out param: cpupower -c 1 info -> cpupower info */
 152                        new_argc += 2;
 153                        continue;
 154                } else if (!strcmp(param, "-v") ||
 155                        !strcmp(param, "--version")) {
 156                        print_version();
 157                        exit(EXIT_SUCCESS);
 158#ifdef DEBUG
 159                } else if (!strcmp(param, "-d") || !strcmp(param, "--debug")) {
 160                        be_verbose = 1;
 161                        new_argc++;
 162                        continue;
 163#endif
 164                } else {
 165                        fprintf(stderr, "Unknown option: %s\n", param);
 166                        print_help();
 167                        exit(EXIT_FAILURE);
 168                }
 169        }
 170        *argc -= new_argc;
 171        *argv += new_argc;
 172}
 173
 174int main(int argc, const char *argv[])
 175{
 176        const char *cmd;
 177        unsigned int i, ret;
 178        struct stat statbuf;
 179        struct utsname uts;
 180        char pathname[32];
 181
 182        cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF));
 183        online_cpus = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF));
 184        offline_cpus = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF));
 185
 186        argc--;
 187        argv += 1;
 188
 189        handle_options(&argc, &argv);
 190
 191        cmd = argv[0];
 192
 193        if (argc < 1) {
 194                print_help();
 195                return EXIT_FAILURE;
 196        }
 197
 198        setlocale(LC_ALL, "");
 199        textdomain(PACKAGE);
 200
 201        /* Turn "perf cmd --help" into "perf help cmd" */
 202        if (argc > 1 && !strcmp(argv[1], "--help")) {
 203                argv[1] = argv[0];
 204                argv[0] = cmd = "help";
 205        }
 206
 207        base_cpu = sched_getcpu();
 208        if (base_cpu < 0) {
 209                fprintf(stderr, _("No valid cpus found.\n"));
 210                return EXIT_FAILURE;
 211        }
 212
 213        get_cpu_info(&cpupower_cpu_info);
 214        run_as_root = !geteuid();
 215        if (run_as_root) {
 216                ret = uname(&uts);
 217                sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
 218                if (!ret && !strcmp(uts.machine, "x86_64") &&
 219                    stat(pathname, &statbuf) != 0) {
 220                        if (system("modprobe msr") == -1)
 221        fprintf(stderr, _("MSR access not available.\n"));
 222                }
 223        }
 224
 225        for (i = 0; i < ARRAY_SIZE(commands); i++) {
 226                struct cmd_struct *p = commands + i;
 227                if (strcmp(p->cmd, cmd))
 228                        continue;
 229                if (!run_as_root && p->needs_root) {
 230                        fprintf(stderr, _("Subcommand %s needs root "
 231                                          "privileges\n"), cmd);
 232                        return EXIT_FAILURE;
 233                }
 234                ret = p->main(argc, argv);
 235                if (cpus_chosen)
 236                        bitmask_free(cpus_chosen);
 237                if (online_cpus)
 238                        bitmask_free(online_cpus);
 239                if (offline_cpus)
 240                        bitmask_free(offline_cpus);
 241                return ret;
 242        }
 243        print_help();
 244        return EXIT_FAILURE;
 245}
 246