2 * chcpu - CPU configuration tool
4 * Copyright IBM Corp. 2011
5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it would be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include <sys/utsname.h>
33 #include <sys/types.h>
44 #define _PATH_SYS_CPU "/sys/devices/system/cpu"
45 #define _PATH_SYS_CPU_ONLINE _PATH_SYS_CPU "/online"
46 #define _PATH_SYS_CPU_RESCAN _PATH_SYS_CPU "/rescan"
47 #define _PATH_SYS_CPU_DISPATCH _PATH_SYS_CPU "/dispatching"
49 static cpu_set_t
*onlinecpus
;
52 #define is_cpu_online(cpu) (CPU_ISSET_S((cpu), CPU_ALLOC_SIZE(maxcpus), onlinecpus))
53 #define num_online_cpus() (CPU_COUNT_S(CPU_ALLOC_SIZE(maxcpus), onlinecpus))
61 CMD_CPU_DISPATCH_HORIZONTAL
,
62 CMD_CPU_DISPATCH_VERTICAL
,
65 static int cpu_enable(cpu_set_t
*cpu_set
, size_t setsize
, int enable
)
71 for (cpu
= 0; cpu
< setsize
; cpu
++) {
72 if (!CPU_ISSET(cpu
, cpu_set
))
74 if (!path_exist(_PATH_SYS_CPU
"/cpu%d", cpu
)) {
75 printf(_("CPU %d does not exist\n"), cpu
);
78 if (!path_exist(_PATH_SYS_CPU
"/cpu%d/online", cpu
)) {
79 printf(_("CPU %d is not hot pluggable\n"), cpu
);
82 online
= path_getnum(_PATH_SYS_CPU
"/cpu%d/online", cpu
);
83 if ((online
== 1) && (enable
== 1)) {
84 printf(_("CPU %d is already enabled\n"), cpu
);
87 if ((online
== 0) && (enable
== 0)) {
88 printf(_("CPU %d is already disabled\n"), cpu
);
91 if (path_exist(_PATH_SYS_CPU
"/cpu%d/configure", cpu
))
92 configured
= path_getnum(_PATH_SYS_CPU
"/cpu%d/configure", cpu
);
94 rc
= path_writestr("1", _PATH_SYS_CPU
"/cpu%d/online", cpu
);
95 if ((rc
== -1) && (configured
== 0))
96 printf(_("CPU %d enable failed "
97 "(CPU is deconfigured)\n"), cpu
);
99 printf(_("CPU %d enable failed (%m)\n"), cpu
);
101 printf(_("CPU %d enabled\n"), cpu
);
103 if (onlinecpus
&& num_online_cpus() == 1) {
104 printf(_("CPU %d disable failed "
105 "(last enabled CPU)\n"), cpu
);
108 rc
= path_writestr("0", _PATH_SYS_CPU
"/cpu%d/online", cpu
);
110 printf(_("CPU %d disable failed (%m)\n"), cpu
);
112 printf(_("CPU %d disabled\n"), cpu
);
114 CPU_CLR(cpu
, onlinecpus
);
121 static int cpu_rescan(void)
123 if (!path_exist(_PATH_SYS_CPU_RESCAN
))
124 errx(EXIT_FAILURE
, _("This system does not support rescanning of CPUs"));
125 if (path_writestr("1", _PATH_SYS_CPU_RESCAN
) == -1)
126 err(EXIT_FAILURE
, _("Failed to trigger rescan of CPUs"));
127 printf(_("Triggered rescan of CPUs\n"));
131 static int cpu_set_dispatch(int mode
)
133 if (!path_exist(_PATH_SYS_CPU_DISPATCH
))
134 errx(EXIT_FAILURE
, _("This system does not support setting "
135 "the dispatching mode of CPUs"));
137 if (path_writestr("0", _PATH_SYS_CPU_DISPATCH
) == -1)
138 err(EXIT_FAILURE
, _("Failed to set horizontal dispatch mode"));
139 printf(_("Succesfully set horizontal dispatching mode\n"));
141 if (path_writestr("1", _PATH_SYS_CPU_DISPATCH
) == -1)
142 err(EXIT_FAILURE
, _("Failed to set vertical dispatch mode"));
143 printf(_("Succesfully set vertical dispatching mode\n"));
148 static int cpu_configure(cpu_set_t
*cpu_set
, size_t setsize
, int configure
)
153 for (cpu
= 0; cpu
< setsize
; cpu
++) {
154 if (!CPU_ISSET(cpu
, cpu_set
))
156 if (!path_exist(_PATH_SYS_CPU
"/cpu%d", cpu
)) {
157 printf(_("CPU %d does not exist\n"), cpu
);
160 if (!path_exist(_PATH_SYS_CPU
"/cpu%d/configure", cpu
)) {
161 printf(_("CPU %d is not configurable\n"), cpu
);
164 current
= path_getnum(_PATH_SYS_CPU
"/cpu%d/configure", cpu
);
165 if ((current
== 1) && (configure
== 1)) {
166 printf(_("CPU %d is already configured\n"), cpu
);
169 if ((current
== 0) && (configure
== 0)) {
170 printf(_("CPU %d is already deconfigured\n"), cpu
);
173 if ((current
== 1) && (configure
== 0) && onlinecpus
&&
174 is_cpu_online(cpu
)) {
175 printf(_("CPU %d deconfigure failed "
176 "(CPU is enabled)\n"), cpu
);
180 rc
= path_writestr("1", _PATH_SYS_CPU
"/cpu%d/configure", cpu
);
182 printf(_("CPU %d configure failed (%m)\n"), cpu
);
184 printf(_("CPU %d configured\n"), cpu
);
186 rc
= path_writestr("0", _PATH_SYS_CPU
"/cpu%d/configure", cpu
);
188 printf(_("CPU %d deconfigure failed (%m)\n"), cpu
);
190 printf(_("CPU %d deconfigured\n"), cpu
);
196 static void cpu_parse(char *cpu_string
, cpu_set_t
*cpu_set
, size_t setsize
)
200 rc
= cpulist_parse(cpu_string
, cpu_set
, setsize
, 1);
204 errx(EXIT_FAILURE
, _("invalid CPU number in CPU list: %s"), cpu_string
);
205 errx(EXIT_FAILURE
, _("failed to parse CPU list: %s"), cpu_string
);
208 static void __attribute__((__noreturn__
)) usage(FILE *out
)
212 " %s [options]\n"), program_invocation_short_name
);
214 puts(_( "\nOptions:\n"
215 " -h, --help print this help\n"
216 " -e, --enable <cpu-list> enable cpus\n"
217 " -d, --disable <cpu-list> disable cpus\n"
218 " -c, --configure <cpu-list> configure cpus\n"
219 " -g, --deconfigure <cpu-list> deconfigure cpus\n"
220 " -p, --dispatch <mode> set dispatching mode\n"
221 " -r, --rescan trigger rescan of cpus\n"
222 " -V, --version output version information and exit\n"));
224 exit(out
== stderr
? EXIT_FAILURE
: EXIT_SUCCESS
);
227 int main(int argc
, char *argv
[])
234 static const struct option longopts
[] = {
235 { "configure", required_argument
, 0, 'c' },
236 { "deconfigure",required_argument
, 0, 'g' },
237 { "disable", required_argument
, 0, 'd' },
238 { "dispatch", required_argument
, 0, 'p' },
239 { "enable", required_argument
, 0, 'e' },
240 { "help", no_argument
, 0, 'h' },
241 { "rescan", no_argument
, 0, 'r' },
242 { "version", no_argument
, 0, 'V' },
246 setlocale(LC_ALL
, "");
247 bindtextdomain(PACKAGE
, LOCALEDIR
);
250 maxcpus
= get_max_number_of_cpus();
252 errx(EXIT_FAILURE
, _("cannot determine NR_CPUS; aborting"));
253 if (path_exist(_PATH_SYS_CPU_ONLINE
))
254 onlinecpus
= path_cpulist(maxcpus
, _PATH_SYS_CPU_ONLINE
);
255 setsize
= CPU_ALLOC_SIZE(maxcpus
);
256 cpu_set
= CPU_ALLOC(maxcpus
);
258 err(EXIT_FAILURE
, _("cpuset_alloc failed"));
260 while ((c
= getopt_long(argc
, argv
, "c:d:e:g:hp:rV", longopts
, NULL
)) != -1) {
261 if (cmd
!= -1 && strchr("cdegpr", c
))
263 _("configure, deconfigure, disable, dispatch, enable "
264 "and rescan are mutually exclusive"));
267 cmd
= CMD_CPU_CONFIGURE
;
268 cpu_parse(argv
[optind
- 1], cpu_set
, setsize
);
271 cmd
= CMD_CPU_DISABLE
;
272 cpu_parse(argv
[optind
- 1], cpu_set
, setsize
);
275 cmd
= CMD_CPU_ENABLE
;
276 cpu_parse(argv
[optind
- 1], cpu_set
, setsize
);
279 cmd
= CMD_CPU_DECONFIGURE
;
280 cpu_parse(argv
[optind
- 1], cpu_set
, setsize
);
285 if (strcmp("horizontal", argv
[optind
- 1]) == 0)
286 cmd
= CMD_CPU_DISPATCH_HORIZONTAL
;
287 else if (strcmp("vertical", argv
[optind
- 1]) == 0)
288 cmd
= CMD_CPU_DISPATCH_VERTICAL
;
290 errx(EXIT_FAILURE
, _("unsupported argument: %s"),
294 cmd
= CMD_CPU_RESCAN
;
297 printf(_("%s from %s\n"), program_invocation_short_name
,
305 if ((argc
== 1) || (argc
!= optind
))
310 return cpu_enable(cpu_set
, maxcpus
, 1);
311 case CMD_CPU_DISABLE
:
312 return cpu_enable(cpu_set
, maxcpus
, 0);
313 case CMD_CPU_CONFIGURE
:
314 return cpu_configure(cpu_set
, maxcpus
, 1);
315 case CMD_CPU_DECONFIGURE
:
316 return cpu_configure(cpu_set
, maxcpus
, 0);
319 case CMD_CPU_DISPATCH_HORIZONTAL
:
320 return cpu_set_dispatch(0);
321 case CMD_CPU_DISPATCH_VERTICAL
:
322 return cpu_set_dispatch(1);