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 along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <sys/utsname.h>
33 #include <sys/types.h>
43 #include "closestream.h"
46 #define EXCL_ERROR "--{configure,deconfigure,disable,dispatch,enable}"
48 /* partial success, otherwise we return regular EXIT_{SUCCESS,FAILURE} */
49 #define CHCPU_EXIT_SOMEOK 64
51 #define _PATH_SYS_CPU "/sys/devices/system/cpu"
52 #define _PATH_SYS_CPU_ONLINE _PATH_SYS_CPU "/online"
53 #define _PATH_SYS_CPU_RESCAN _PATH_SYS_CPU "/rescan"
54 #define _PATH_SYS_CPU_DISPATCH _PATH_SYS_CPU "/dispatching"
56 static cpu_set_t
*onlinecpus
;
59 #define is_cpu_online(cpu) (CPU_ISSET_S((cpu), CPU_ALLOC_SIZE(maxcpus), onlinecpus))
60 #define num_online_cpus() (CPU_COUNT_S(CPU_ALLOC_SIZE(maxcpus), onlinecpus))
68 CMD_CPU_DISPATCH_HORIZONTAL
,
69 CMD_CPU_DISPATCH_VERTICAL
,
72 /* returns: 0 = success
74 * > 0 = partial success
76 static int cpu_enable(cpu_set_t
*cpu_set
, size_t setsize
, int enable
)
83 for (cpu
= 0; cpu
< setsize
; cpu
++) {
84 if (!CPU_ISSET(cpu
, cpu_set
))
86 if (!path_exist(_PATH_SYS_CPU
"/cpu%d", cpu
)) {
87 printf(_("CPU %d does not exist\n"), cpu
);
91 if (!path_exist(_PATH_SYS_CPU
"/cpu%d/online", cpu
)) {
92 printf(_("CPU %d is not hot pluggable\n"), cpu
);
96 online
= path_read_s32(_PATH_SYS_CPU
"/cpu%d/online", cpu
);
97 if ((online
== 1) && (enable
== 1)) {
98 printf(_("CPU %d is already enabled\n"), cpu
);
101 if ((online
== 0) && (enable
== 0)) {
102 printf(_("CPU %d is already disabled\n"), cpu
);
105 if (path_exist(_PATH_SYS_CPU
"/cpu%d/configure", cpu
))
106 configured
= path_read_s32(_PATH_SYS_CPU
"/cpu%d/configure", cpu
);
108 rc
= path_write_str("1", _PATH_SYS_CPU
"/cpu%d/online", cpu
);
109 if ((rc
== -1) && (configured
== 0)) {
110 warnx(_("CPU %d enable failed "
111 "(CPU is deconfigured)"), cpu
);
113 } else if (rc
== -1) {
114 warn(_("CPU %d enable failed"), cpu
);
117 printf(_("CPU %d enabled\n"), cpu
);
119 if (onlinecpus
&& num_online_cpus() == 1) {
120 printf(_("CPU %d disable failed "
121 "(last enabled CPU)\n"), cpu
);
125 rc
= path_write_str("0", _PATH_SYS_CPU
"/cpu%d/online", cpu
);
127 warn(_("CPU %d disable failed"), cpu
);
130 printf(_("CPU %d disabled\n"), cpu
);
132 CPU_CLR(cpu
, onlinecpus
);
137 return fails
== 0 ? 0 : fails
== setsize
? -1 : 1;
140 static int cpu_rescan(void)
142 if (!path_exist(_PATH_SYS_CPU_RESCAN
))
143 errx(EXIT_FAILURE
, _("This system does not support rescanning of CPUs"));
144 if (path_write_str("1", _PATH_SYS_CPU_RESCAN
) == -1)
145 err(EXIT_FAILURE
, _("Failed to trigger rescan of CPUs"));
146 printf(_("Triggered rescan of CPUs\n"));
150 static int cpu_set_dispatch(int mode
)
152 if (!path_exist(_PATH_SYS_CPU_DISPATCH
))
153 errx(EXIT_FAILURE
, _("This system does not support setting "
154 "the dispatching mode of CPUs"));
156 if (path_write_str("0", _PATH_SYS_CPU_DISPATCH
) == -1)
157 err(EXIT_FAILURE
, _("Failed to set horizontal dispatch mode"));
158 printf(_("Successfully set horizontal dispatching mode\n"));
160 if (path_write_str("1", _PATH_SYS_CPU_DISPATCH
) == -1)
161 err(EXIT_FAILURE
, _("Failed to set vertical dispatch mode"));
162 printf(_("Successfully set vertical dispatching mode\n"));
167 /* returns: 0 = success
169 * > 0 = partial success
171 static int cpu_configure(cpu_set_t
*cpu_set
, size_t setsize
, int configure
)
177 for (cpu
= 0; cpu
< setsize
; cpu
++) {
178 if (!CPU_ISSET(cpu
, cpu_set
))
180 if (!path_exist(_PATH_SYS_CPU
"/cpu%d", cpu
)) {
181 printf(_("CPU %d does not exist\n"), cpu
);
185 if (!path_exist(_PATH_SYS_CPU
"/cpu%d/configure", cpu
)) {
186 printf(_("CPU %d is not configurable\n"), cpu
);
190 current
= path_read_s32(_PATH_SYS_CPU
"/cpu%d/configure", cpu
);
191 if ((current
== 1) && (configure
== 1)) {
192 printf(_("CPU %d is already configured\n"), cpu
);
195 if ((current
== 0) && (configure
== 0)) {
196 printf(_("CPU %d is already deconfigured\n"), cpu
);
199 if ((current
== 1) && (configure
== 0) && onlinecpus
&&
200 is_cpu_online(cpu
)) {
201 printf(_("CPU %d deconfigure failed "
202 "(CPU is enabled)\n"), cpu
);
207 rc
= path_write_str("1", _PATH_SYS_CPU
"/cpu%d/configure", cpu
);
209 warn(_("CPU %d configure failed"), cpu
);
212 printf(_("CPU %d configured\n"), cpu
);
214 rc
= path_write_str("0", _PATH_SYS_CPU
"/cpu%d/configure", cpu
);
216 warn(_("CPU %d deconfigure failed"), cpu
);
219 printf(_("CPU %d deconfigured\n"), cpu
);
223 return fails
== 0 ? 0 : fails
== setsize
? -1 : 1;
226 static void cpu_parse(char *cpu_string
, cpu_set_t
*cpu_set
, size_t setsize
)
230 rc
= cpulist_parse(cpu_string
, cpu_set
, setsize
, 1);
234 errx(EXIT_FAILURE
, _("invalid CPU number in CPU list: %s"), cpu_string
);
235 errx(EXIT_FAILURE
, _("failed to parse CPU list: %s"), cpu_string
);
238 static void __attribute__((__noreturn__
)) usage(FILE *out
)
242 " %s [options]\n"), program_invocation_short_name
);
244 puts(_( "\nOptions:\n"
245 " -h, --help print this help\n"
246 " -e, --enable <cpu-list> enable cpus\n"
247 " -d, --disable <cpu-list> disable cpus\n"
248 " -c, --configure <cpu-list> configure cpus\n"
249 " -g, --deconfigure <cpu-list> deconfigure cpus\n"
250 " -p, --dispatch <mode> set dispatching mode\n"
251 " -r, --rescan trigger rescan of cpus\n"
252 " -V, --version output version information and exit\n"));
254 exit(out
== stderr
? EXIT_FAILURE
: EXIT_SUCCESS
);
257 int main(int argc
, char *argv
[])
264 static const struct option longopts
[] = {
265 { "configure", required_argument
, 0, 'c' },
266 { "deconfigure",required_argument
, 0, 'g' },
267 { "disable", required_argument
, 0, 'd' },
268 { "dispatch", required_argument
, 0, 'p' },
269 { "enable", required_argument
, 0, 'e' },
270 { "help", no_argument
, 0, 'h' },
271 { "rescan", no_argument
, 0, 'r' },
272 { "version", no_argument
, 0, 'V' },
276 static const ul_excl_t excl
[] = { /* rows and cols in in ASCII order */
277 { 'c','d','e','g','p' },
280 int excl_st
[ARRAY_SIZE(excl
)] = UL_EXCL_STATUS_INIT
;
282 setlocale(LC_ALL
, "");
283 bindtextdomain(PACKAGE
, LOCALEDIR
);
285 atexit(close_stdout
);
287 maxcpus
= get_max_number_of_cpus();
289 errx(EXIT_FAILURE
, _("cannot determine NR_CPUS; aborting"));
290 if (path_exist(_PATH_SYS_CPU_ONLINE
))
291 onlinecpus
= path_read_cpulist(maxcpus
, _PATH_SYS_CPU_ONLINE
);
292 setsize
= CPU_ALLOC_SIZE(maxcpus
);
293 cpu_set
= CPU_ALLOC(maxcpus
);
295 err(EXIT_FAILURE
, _("cpuset_alloc failed"));
297 while ((c
= getopt_long(argc
, argv
, "c:d:e:g:hp:rV", longopts
, NULL
)) != -1) {
299 err_exclusive_options(c
, longopts
, excl
, excl_st
);
303 cmd
= CMD_CPU_CONFIGURE
;
304 cpu_parse(argv
[optind
- 1], cpu_set
, setsize
);
307 cmd
= CMD_CPU_DISABLE
;
308 cpu_parse(argv
[optind
- 1], cpu_set
, setsize
);
311 cmd
= CMD_CPU_ENABLE
;
312 cpu_parse(argv
[optind
- 1], cpu_set
, setsize
);
315 cmd
= CMD_CPU_DECONFIGURE
;
316 cpu_parse(argv
[optind
- 1], cpu_set
, setsize
);
321 if (strcmp("horizontal", argv
[optind
- 1]) == 0)
322 cmd
= CMD_CPU_DISPATCH_HORIZONTAL
;
323 else if (strcmp("vertical", argv
[optind
- 1]) == 0)
324 cmd
= CMD_CPU_DISPATCH_VERTICAL
;
326 errx(EXIT_FAILURE
, _("unsupported argument: %s"),
330 cmd
= CMD_CPU_RESCAN
;
333 printf(_("%s from %s\n"), program_invocation_short_name
,
341 if ((argc
== 1) || (argc
!= optind
))
346 rc
= cpu_enable(cpu_set
, maxcpus
, 1);
348 case CMD_CPU_DISABLE
:
349 rc
= cpu_enable(cpu_set
, maxcpus
, 0);
351 case CMD_CPU_CONFIGURE
:
352 rc
= cpu_configure(cpu_set
, maxcpus
, 1);
354 case CMD_CPU_DECONFIGURE
:
355 rc
= cpu_configure(cpu_set
, maxcpus
, 0);
360 case CMD_CPU_DISPATCH_HORIZONTAL
:
361 rc
= cpu_set_dispatch(0);
363 case CMD_CPU_DISPATCH_VERTICAL
:
364 rc
= cpu_set_dispatch(1);
371 return rc
== 0 ? EXIT_SUCCESS
:
372 rc
< 0 ? EXIT_FAILURE
: CHCPU_EXIT_SOMEOK
;