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