cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cpupower.c (5586B)


      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}