1 /*
2 * xenpm.c: list the power information of the available processors
3 * Copyright (c) 2008, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; If not, see <http://www.gnu.org/licenses/>.
16 */
17 #define MAX_NR_CPU 512
18
19 #include <ctype.h>
20 #include <limits.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <getopt.h>
26 #include <errno.h>
27 #include <signal.h>
28
29 #include <xenctrl.h>
30 #include <inttypes.h>
31 #include <sys/time.h>
32
33 #include <xen-tools/common-macros.h>
34
35 #define MAX_PKG_RESIDENCIES 12
36 #define MAX_CORE_RESIDENCIES 8
37
38 static xc_interface *xc_handle;
39 static unsigned int max_cpu_nr;
40
41 /* help message */
show_help(void)42 void show_help(void)
43 {
44 fprintf(stderr,
45 "xen power management control tool\n\n"
46 "usage: xenpm <command> [args]\n\n"
47 "xenpm command list:\n\n"
48 " get-cpuidle-states [cpuid] list cpu idle info of CPU <cpuid> or all\n"
49 " get-cpufreq-states [cpuid] list cpu freq info of CPU <cpuid> or all\n"
50 " get-cpufreq-average [cpuid] average cpu frequency since last invocation\n"
51 " for CPU <cpuid> or all\n"
52 " get-cpufreq-para [cpuid] list cpu freq parameter of CPU <cpuid> or all\n"
53 " set-scaling-maxfreq [cpuid] <HZ> set max cpu frequency <HZ> on CPU <cpuid>\n"
54 " or all CPUs\n"
55 " set-scaling-minfreq [cpuid] <HZ> set min cpu frequency <HZ> on CPU <cpuid>\n"
56 " or all CPUs\n"
57 " set-scaling-speed [cpuid] <num> set scaling speed on CPU <cpuid> or all\n"
58 " it is used in userspace governor.\n"
59 " set-scaling-governor [cpuid] <gov> set scaling governor on CPU <cpuid> or all\n"
60 " as userspace/performance/powersave/ondemand\n"
61 " set-sampling-rate [cpuid] <num> set sampling rate on CPU <cpuid> or all\n"
62 " it is used in ondemand governor.\n"
63 " set-up-threshold [cpuid] <num> set up threshold on CPU <cpuid> or all\n"
64 " it is used in ondemand governor.\n"
65 " get-cpu-topology get thread/core/socket topology info\n"
66 " set-sched-smt enable|disable enable/disable scheduler smt power saving\n"
67 " set-vcpu-migration-delay <num> set scheduler vcpu migration delay in us\n"
68 " get-vcpu-migration-delay get scheduler vcpu migration delay\n"
69 " set-max-cstate <num>|'unlimited' [<num2>|'unlimited']\n"
70 " set the C-State limitation (<num> >= 0) and\n"
71 " optionally the C-sub-state limitation (<num2> >= 0)\n"
72 " set-cpufreq-cppc [cpuid] [balance|performance|powersave] <param:val>*\n"
73 " set Hardware P-State (HWP) parameters\n"
74 " on CPU <cpuid> or all if omitted.\n"
75 " optionally a preset of one of:\n"
76 " balance|performance|powersave\n"
77 " an optional list of param:val arguments\n"
78 " minimum:N (0-255)\n"
79 " maximum:N (0-255)\n"
80 " get-cpufreq-para lowest/highest\n"
81 " values are limits for\n"
82 " minumum/maximum.\n"
83 " desired:N (0-255)\n"
84 " set explicit performance target.\n"
85 " non-zero disables auto-HWP mode.\n"
86 " energy-perf:N (0-255)\n"
87 " energy/performance hint\n"
88 " lower - favor performance\n"
89 " higher - favor powersave\n"
90 " 128 - balance\n"
91 " act-window:N{,m,u}s range 1us-1270s\n"
92 " window for internal calculations.\n"
93 " units default to \"us\" if unspecified.\n"
94 " truncates un-representable values.\n"
95 " 0 lets the hardware decide.\n"
96 " start [seconds] start collect Cx/Px statistics,\n"
97 " output after CTRL-C or SIGINT or several seconds.\n"
98 " enable-turbo-mode [cpuid] enable Turbo Mode for processors that support it.\n"
99 " disable-turbo-mode [cpuid] disable Turbo Mode for processors that support it.\n"
100 );
101 }
102 /* wrapper function */
help_func(int argc,char * argv[])103 void help_func(int argc, char *argv[])
104 {
105 show_help();
106 }
107
parse_cpuid(const char * arg,int * cpuid)108 static void parse_cpuid(const char *arg, int *cpuid)
109 {
110 if ( sscanf(arg, "%d", cpuid) != 1 || *cpuid < 0 )
111 {
112 if ( strcasecmp(arg, "all") )
113 {
114 fprintf(stderr, "Invalid CPU identifier: '%s'\n", arg);
115 exit(EINVAL);
116 }
117 *cpuid = -1;
118 }
119 }
120
parse_cpuid_and_int(int argc,char * argv[],int * cpuid,int * val,const char * what)121 static void parse_cpuid_and_int(int argc, char *argv[],
122 int *cpuid, int *val, const char *what)
123 {
124 if ( argc == 0 )
125 {
126 fprintf(stderr, "Missing %s\n", what);
127 exit(EINVAL);
128 }
129
130 if ( argc > 1 )
131 parse_cpuid(argv[0], cpuid);
132
133 if ( sscanf(argv[argc > 1], "%d", val) != 1 )
134 {
135 fprintf(stderr, "Invalid %s '%s'\n", what, argv[argc > 1]);
136 exit(EINVAL);
137 }
138 }
139
print_cxstat(int cpuid,struct xc_cx_stat * cxstat)140 static void print_cxstat(int cpuid, struct xc_cx_stat *cxstat)
141 {
142 unsigned int i;
143
144 printf("cpu id : %d\n", cpuid);
145 printf("total C-states : %d\n", cxstat->nr);
146 printf("idle time(ms) : %"PRIu64"\n",
147 cxstat->idle_time/1000000UL);
148 for ( i = 0; i < cxstat->nr; i++ )
149 {
150 printf("C%-20d: transition [%20"PRIu64"]\n",
151 i, cxstat->triggers[i]);
152 printf(" residency [%20"PRIu64" ms]\n",
153 cxstat->residencies[i]/1000000UL);
154 }
155 for ( i = 0; i < MAX_PKG_RESIDENCIES && i < cxstat->nr_pc; ++i )
156 if ( cxstat->pc[i] )
157 printf("pc%d : [%20"PRIu64" ms]\n", i + 1,
158 cxstat->pc[i] / 1000000UL);
159 for ( i = 0; i < MAX_CORE_RESIDENCIES && i < cxstat->nr_cc; ++i )
160 if ( cxstat->cc[i] )
161 printf("cc%d : [%20"PRIu64" ms]\n", i + 1,
162 cxstat->cc[i] / 1000000UL);
163 printf("\n");
164 }
165
166 /* show cpu idle information on CPU cpuid */
get_cxstat_by_cpuid(xc_interface * xc_handle,int cpuid,struct xc_cx_stat * cxstat)167 static int get_cxstat_by_cpuid(xc_interface *xc_handle, int cpuid, struct xc_cx_stat *cxstat)
168 {
169 int ret = 0;
170 int max_cx_num = 0;
171
172 ret = xc_pm_get_max_cx(xc_handle, cpuid, &max_cx_num);
173 if ( ret )
174 return -errno;
175
176 if ( !cxstat )
177 return -EINVAL;
178
179 if ( !max_cx_num )
180 return -ENODEV;
181
182 cxstat->triggers = calloc(max_cx_num, sizeof(*cxstat->triggers));
183 cxstat->residencies = calloc(max_cx_num, sizeof(*cxstat->residencies));
184 cxstat->pc = calloc(MAX_PKG_RESIDENCIES, sizeof(*cxstat->pc));
185 cxstat->cc = calloc(MAX_CORE_RESIDENCIES, sizeof(*cxstat->cc));
186 if ( !cxstat->triggers || !cxstat->residencies ||
187 !cxstat->pc || !cxstat->cc )
188 {
189 free(cxstat->cc);
190 free(cxstat->pc);
191 free(cxstat->residencies);
192 free(cxstat->triggers);
193 return -ENOMEM;
194 }
195
196 cxstat->nr = max_cx_num;
197 cxstat->nr_pc = MAX_PKG_RESIDENCIES;
198 cxstat->nr_cc = MAX_CORE_RESIDENCIES;
199
200 ret = xc_pm_get_cxstat(xc_handle, cpuid, cxstat);
201 if( ret )
202 {
203 ret = -errno;
204 free(cxstat->triggers);
205 free(cxstat->residencies);
206 free(cxstat->pc);
207 free(cxstat->cc);
208 cxstat->triggers = NULL;
209 cxstat->residencies = NULL;
210 cxstat->pc = NULL;
211 cxstat->cc = NULL;
212 }
213
214 return ret;
215 }
216
show_max_cstate(xc_interface * xc_handle)217 static int show_max_cstate(xc_interface *xc_handle)
218 {
219 int ret = 0;
220 uint32_t value;
221
222 if ( (ret = xc_get_cpuidle_max_cstate(xc_handle, &value)) )
223 return ret;
224
225 if ( value < XEN_SYSCTL_CX_UNLIMITED )
226 {
227 printf("Max possible C-state: C%"PRIu32"\n", value);
228 if ( (ret = xc_get_cpuidle_max_csubstate(xc_handle, &value)) )
229 return ret;
230 if ( value < XEN_SYSCTL_CX_UNLIMITED )
231 printf("Max possible substate: %"PRIu32"\n\n", value);
232 else
233 puts("");
234 }
235 else
236 printf("All C-states allowed\n\n");
237
238 return 0;
239 }
240
show_cxstat_by_cpuid(xc_interface * xc_handle,int cpuid)241 static int show_cxstat_by_cpuid(xc_interface *xc_handle, int cpuid)
242 {
243 int ret = 0;
244 struct xc_cx_stat cxstatinfo;
245
246 ret = get_cxstat_by_cpuid(xc_handle, cpuid, &cxstatinfo);
247 if ( ret )
248 {
249 if ( ret == -ENODEV )
250 fprintf(stderr,
251 "Either Xen cpuidle is disabled or no valid information is registered!\n");
252 return ret;
253 }
254
255 print_cxstat(cpuid, &cxstatinfo);
256
257 free(cxstatinfo.triggers);
258 free(cxstatinfo.residencies);
259 free(cxstatinfo.pc);
260 free(cxstatinfo.cc);
261 return 0;
262 }
263
cxstat_func(int argc,char * argv[])264 void cxstat_func(int argc, char *argv[])
265 {
266 int cpuid = -1;
267
268 if ( argc > 0 )
269 parse_cpuid(argv[0], &cpuid);
270
271 show_max_cstate(xc_handle);
272
273 if ( cpuid < 0 )
274 {
275 /* show cxstates on all cpus */
276 int i;
277 for ( i = 0; i < max_cpu_nr; i++ )
278 if ( show_cxstat_by_cpuid(xc_handle, i) == -ENODEV )
279 break;
280 }
281 else
282 show_cxstat_by_cpuid(xc_handle, cpuid);
283 }
284
print_pxstat(int cpuid,struct xc_px_stat * pxstat)285 static void print_pxstat(int cpuid, struct xc_px_stat *pxstat)
286 {
287 int i;
288
289 printf("cpu id : %d\n", cpuid);
290 printf("total P-states : %d\n", pxstat->total);
291 printf("usable P-states : %d\n", pxstat->usable);
292 printf("current frequency : %"PRIu64" MHz\n",
293 pxstat->pt[pxstat->cur].freq);
294 for ( i = 0; i < pxstat->total; i++ )
295 {
296 if ( pxstat->cur == i )
297 printf("*P%-9d", i);
298 else
299 printf("P%-10d", i);
300 printf("[%4"PRIu64" MHz]", pxstat->pt[i].freq);
301 printf(": transition [%20"PRIu64"]\n",
302 pxstat->pt[i].count);
303 printf(" residency [%20"PRIu64" ms]\n",
304 pxstat->pt[i].residency/1000000UL);
305 }
306 printf("\n");
307 }
308
309 /* show cpu frequency information on CPU cpuid */
get_pxstat_by_cpuid(xc_interface * xc_handle,int cpuid,struct xc_px_stat * pxstat)310 static int get_pxstat_by_cpuid(xc_interface *xc_handle, int cpuid, struct xc_px_stat *pxstat)
311 {
312 int ret = 0;
313 int max_px_num = 0;
314
315 ret = xc_pm_get_max_px(xc_handle, cpuid, &max_px_num);
316 if ( ret )
317 return -errno;
318
319 if ( !pxstat)
320 return -EINVAL;
321
322 pxstat->trans_pt = malloc(max_px_num * max_px_num *
323 sizeof(uint64_t));
324 if ( !pxstat->trans_pt )
325 return -ENOMEM;
326 pxstat->pt = malloc(max_px_num * sizeof(struct xc_px_val));
327 if ( !pxstat->pt )
328 {
329 free(pxstat->trans_pt);
330 return -ENOMEM;
331 }
332
333 ret = xc_pm_get_pxstat(xc_handle, cpuid, pxstat);
334 if( ret )
335 {
336 ret = -errno;
337 free(pxstat->trans_pt);
338 free(pxstat->pt);
339 pxstat->trans_pt = NULL;
340 pxstat->pt = NULL;
341 }
342
343 return ret;
344 }
345
346 /* show cpu actual average freq information on CPU cpuid */
get_avgfreq_by_cpuid(xc_interface * xc_handle,int cpuid,int * avgfreq)347 static int get_avgfreq_by_cpuid(xc_interface *xc_handle, int cpuid, int *avgfreq)
348 {
349 int ret = 0;
350
351 ret = xc_get_cpufreq_avgfreq(xc_handle, cpuid, avgfreq);
352 if ( ret )
353 ret = -errno;
354
355 return ret;
356 }
357
show_pxstat_by_cpuid(xc_interface * xc_handle,int cpuid)358 static int show_pxstat_by_cpuid(xc_interface *xc_handle, int cpuid)
359 {
360 int ret = 0;
361 struct xc_px_stat pxstatinfo;
362
363 ret = get_pxstat_by_cpuid(xc_handle, cpuid, &pxstatinfo);
364 if ( ret )
365 {
366 if ( ret == -ENODEV )
367 fprintf(stderr,
368 "Either Xen cpufreq is disabled or no valid information is registered!\n");
369 else if ( ret == -EOPNOTSUPP )
370 fprintf(stderr,
371 "P-State information not supported. Try 'get-cpufreq-average' or 'start'.\n");
372 return ret;
373 }
374
375 print_pxstat(cpuid, &pxstatinfo);
376
377 free(pxstatinfo.trans_pt);
378 free(pxstatinfo.pt);
379 return 0;
380 }
381
pxstat_func(int argc,char * argv[])382 void pxstat_func(int argc, char *argv[])
383 {
384 int cpuid = -1;
385
386 if ( argc > 0 )
387 parse_cpuid(argv[0], &cpuid);
388
389 if ( cpuid < 0 )
390 {
391 /* show pxstates on all cpus */
392 int i;
393 for ( i = 0; i < max_cpu_nr; i++ )
394 {
395 int ret = show_pxstat_by_cpuid(xc_handle, i);
396
397 if ( ret == -ENODEV || ret == -EOPNOTSUPP )
398 break;
399 }
400 }
401 else
402 show_pxstat_by_cpuid(xc_handle, cpuid);
403 }
404
show_cpufreq_by_cpuid(xc_interface * xc_handle,int cpuid)405 static int show_cpufreq_by_cpuid(xc_interface *xc_handle, int cpuid)
406 {
407 int ret = 0;
408 int average_cpufreq;
409
410 ret = get_avgfreq_by_cpuid(xc_handle, cpuid, &average_cpufreq);
411 if ( ret )
412 return ret;
413
414 printf("cpu id : %d\n", cpuid);
415 printf("average cpu frequency: %d\n", average_cpufreq);
416 printf("\n");
417 return 0;
418 }
419
cpufreq_func(int argc,char * argv[])420 void cpufreq_func(int argc, char *argv[])
421 {
422 int cpuid = -1;
423
424 if ( argc > 0 )
425 parse_cpuid(argv[0], &cpuid);
426
427 if ( cpuid < 0 )
428 {
429 /* show average frequency on all cpus */
430 int i;
431 for ( i = 0; i < max_cpu_nr; i++ )
432 if ( show_cpufreq_by_cpuid(xc_handle, i) == -ENODEV )
433 break;
434 }
435 else
436 show_cpufreq_by_cpuid(xc_handle, cpuid);
437 }
438
439 static uint64_t usec_start, usec_end;
440 static struct xc_cx_stat *cxstat, *cxstat_start, *cxstat_end;
441 static struct xc_px_stat *pxstat, *pxstat_start, *pxstat_end;
442 static int *avgfreq;
443 static uint64_t *sum, *sum_cx, *sum_px;
444
signal_int_handler(int signo)445 static void signal_int_handler(int signo)
446 {
447 int i, j, k, ret;
448 struct timeval tv;
449 int cx_cap = 0, px_cap = 0;
450 xc_cputopo_t *cputopo = NULL;
451 unsigned max_cpus = 0;
452
453 if ( xc_cputopoinfo(xc_handle, &max_cpus, NULL) != 0 )
454 {
455 fprintf(stderr, "failed to discover number of CPUs: %s\n",
456 strerror(errno));
457 goto out;
458 }
459
460 cputopo = calloc(max_cpus, sizeof(*cputopo));
461 if ( cputopo == NULL )
462 {
463 fprintf(stderr, "failed to allocate hypercall buffers\n");
464 goto out;
465 }
466
467 if ( gettimeofday(&tv, NULL) )
468 {
469 fprintf(stderr, "failed to get timeofday\n");
470 goto out;
471 }
472 usec_end = tv.tv_sec * 1000000UL + tv.tv_usec;
473
474 if ( get_cxstat_by_cpuid(xc_handle, 0, NULL) != -ENODEV )
475 {
476 cx_cap = 1;
477 for ( i = 0; i < max_cpu_nr; i++ )
478 if ( !get_cxstat_by_cpuid(xc_handle, i, &cxstat_end[i]) )
479 for ( j = 0; j < cxstat_end[i].nr; j++ )
480 {
481 int64_t diff = (int64_t)cxstat_end[i].residencies[j] -
482 (int64_t)cxstat_start[i].residencies[j];
483 if ( diff >=0 )
484 sum_cx[i] += diff;
485 }
486 }
487
488 ret = get_pxstat_by_cpuid(xc_handle, 0, NULL);
489 if ( ret != -ENODEV && ret != -EOPNOTSUPP )
490 {
491 px_cap = 1;
492 for ( i = 0; i < max_cpu_nr; i++ )
493 if ( !get_pxstat_by_cpuid(xc_handle, i , &pxstat_end[i]) )
494 for ( j = 0; j < pxstat_end[i].total; j++ )
495 sum_px[i] += pxstat_end[i].pt[j].residency -
496 pxstat_start[i].pt[j].residency;
497 }
498
499 for ( i = 0; i < max_cpu_nr; i++ )
500 get_avgfreq_by_cpuid(xc_handle, i, &avgfreq[i]);
501
502 printf("Elapsed time (ms): %"PRIu64"\n", (usec_end - usec_start) / 1000UL);
503 for ( i = 0; i < max_cpu_nr; i++ )
504 {
505 uint64_t res, triggers;
506 double avg_res;
507
508 printf("\nCPU%d:\tResidency(ms)\t\tAvg Res(ms)\n",i);
509 if ( cx_cap && sum_cx[i] > 0 )
510 {
511 for ( j = 0; j < cxstat_end[i].nr; j++ )
512 {
513 int64_t diff = (int64_t)cxstat_end[i].residencies[j] -
514 (int64_t)cxstat_start[i].residencies[j];
515
516 res = ( diff >= 0 ) ? diff : 0;
517 triggers = cxstat_end[i].triggers[j] -
518 cxstat_start[i].triggers[j];
519 /*
520 * triggers may be zero if the CPU has been in this state for
521 * the whole sample or if it never entered the state
522 */
523 if ( triggers == 0 && cxstat_end[i].last == j )
524 avg_res = (double)sum_cx[i]/1000000.0;
525 else
526 avg_res = (triggers==0) ? 0: (double)res/triggers/1000000.0;
527 printf(" C%d\t%"PRIu64"\t(%5.2f%%)\t%.2f\n", j, res/1000000UL,
528 100 * res / (double)sum_cx[i], avg_res );
529 }
530 printf("\n");
531 }
532 if ( px_cap && sum_px[i]>0 )
533 {
534 for ( j = 0; j < pxstat_end[i].total; j++ )
535 {
536 res = pxstat_end[i].pt[j].residency -
537 pxstat_start[i].pt[j].residency;
538 printf(" P%d\t%"PRIu64"\t(%5.2f%%)\n", j,
539 res / 1000000UL, 100UL * res / (double)sum_px[i]);
540 }
541 }
542 if ( px_cap && avgfreq[i] )
543 printf(" Avg freq\t%d\tKHz\n", avgfreq[i]);
544 }
545
546 if ( cx_cap && !xc_cputopoinfo(xc_handle, &max_cpus, cputopo) )
547 {
548 uint32_t socket_ids[MAX_NR_CPU];
549 uint32_t core_ids[MAX_NR_CPU];
550 uint32_t socket_nr = 0;
551 uint32_t core_nr = 0;
552
553 if ( max_cpus > MAX_NR_CPU )
554 max_cpus = MAX_NR_CPU;
555 /* check validity */
556 for ( i = 0; i < max_cpus; i++ )
557 {
558 if ( cputopo[i].core == XEN_INVALID_CORE_ID ||
559 cputopo[i].socket == XEN_INVALID_SOCKET_ID )
560 break;
561 }
562 if ( i >= max_cpus )
563 {
564 /* find socket nr & core nr per socket */
565 for ( i = 0; i < max_cpus; i++ )
566 {
567 for ( j = 0; j < socket_nr; j++ )
568 if ( cputopo[i].socket == socket_ids[j] )
569 break;
570 if ( j == socket_nr )
571 {
572 socket_ids[j] = cputopo[i].socket;
573 socket_nr++;
574 }
575
576 for ( j = 0; j < core_nr; j++ )
577 if ( cputopo[i].core == core_ids[j] )
578 break;
579 if ( j == core_nr )
580 {
581 core_ids[j] = cputopo[i].core;
582 core_nr++;
583 }
584 }
585
586 /* print out CC? and PC? */
587 for ( i = 0; i < socket_nr; i++ )
588 {
589 unsigned int n;
590 uint64_t res;
591
592 for ( j = 0; j < max_cpus; j++ )
593 {
594 if ( cputopo[j].socket == socket_ids[i] )
595 break;
596 }
597 printf("\nSocket %d\n", socket_ids[i]);
598 for ( n = 0; n < MAX_PKG_RESIDENCIES; ++n )
599 {
600 if ( n >= cxstat_end[j].nr_pc )
601 continue;
602 res = cxstat_end[j].pc[n];
603 if ( n < cxstat_start[j].nr_pc )
604 res -= cxstat_start[j].pc[n];
605 printf("\tPC%u\t%"PRIu64" ms\t%.2f%%\n",
606 n + 1, res / 1000000UL,
607 100UL * res / (double)sum_cx[j]);
608 }
609 for ( k = 0; k < core_nr; k++ )
610 {
611 for ( j = 0; j < max_cpus; j++ )
612 {
613 if ( cputopo[j].socket == socket_ids[i] &&
614 cputopo[j].core == core_ids[k] )
615 break;
616 }
617 printf("\t Core %d CPU %d\n", core_ids[k], j);
618 for ( n = 0; n < MAX_CORE_RESIDENCIES; ++n )
619 {
620 if ( n >= cxstat_end[j].nr_cc )
621 continue;
622 res = cxstat_end[j].cc[n];
623 if ( n < cxstat_start[j].nr_cc )
624 res -= cxstat_start[j].cc[n];
625 printf("\t\tCC%u\t%"PRIu64" ms\t%.2f%%\n",
626 n + 1, res / 1000000UL,
627 100UL * res / (double)sum_cx[j]);
628 }
629 }
630 }
631 }
632 }
633
634 /* some clean up and then exits */
635 for ( i = 0; i < 2 * max_cpu_nr; i++ )
636 {
637 free(cxstat[i].triggers);
638 free(cxstat[i].residencies);
639 free(cxstat[i].pc);
640 free(cxstat[i].cc);
641 free(pxstat[i].trans_pt);
642 free(pxstat[i].pt);
643 }
644 free(cxstat);
645 free(pxstat);
646 free(sum);
647 free(avgfreq);
648 out:
649 free(cputopo);
650 xc_interface_close(xc_handle);
651 exit(0);
652 }
653
start_gather_func(int argc,char * argv[])654 void start_gather_func(int argc, char *argv[])
655 {
656 int i;
657 struct timeval tv;
658 int timeout = 0;
659
660 if ( argc == 1 )
661 {
662 sscanf(argv[0], "%d", &timeout);
663 if ( timeout <= 0 )
664 fprintf(stderr, "failed to set timeout seconds, falling back...\n");
665 else
666 printf("Timeout set to %d seconds\n", timeout);
667 }
668
669 if ( gettimeofday(&tv, NULL) )
670 {
671 fprintf(stderr, "failed to get timeofday\n");
672 return ;
673 }
674 usec_start = tv.tv_sec * 1000000UL + tv.tv_usec;
675
676 sum = calloc(2 * max_cpu_nr, sizeof(*sum));
677 if ( sum == NULL )
678 return ;
679 cxstat = calloc(2 * max_cpu_nr, sizeof(*cxstat));
680 if ( cxstat == NULL )
681 {
682 free(sum);
683 return ;
684 }
685 pxstat = calloc(2 * max_cpu_nr, sizeof(*pxstat));
686 if ( pxstat == NULL )
687 {
688 free(sum);
689 free(cxstat);
690 return ;
691 }
692 avgfreq = calloc(max_cpu_nr, sizeof(*avgfreq));
693 if ( avgfreq == NULL )
694 {
695 free(sum);
696 free(cxstat);
697 free(pxstat);
698 return ;
699 }
700 sum_cx = sum;
701 sum_px = sum + max_cpu_nr;
702 cxstat_start = cxstat;
703 cxstat_end = cxstat + max_cpu_nr;
704 pxstat_start = pxstat;
705 pxstat_end = pxstat + max_cpu_nr;
706
707 if ( get_cxstat_by_cpuid(xc_handle, 0, NULL) == -ENODEV &&
708 get_pxstat_by_cpuid(xc_handle, 0, NULL) == -ENODEV )
709 {
710 fprintf(stderr, "Xen cpu idle and frequency is disabled!\n");
711 return ;
712 }
713
714 for ( i = 0; i < max_cpu_nr; i++ )
715 {
716 get_cxstat_by_cpuid(xc_handle, i, &cxstat_start[i]);
717 get_pxstat_by_cpuid(xc_handle, i, &pxstat_start[i]);
718 get_avgfreq_by_cpuid(xc_handle, i, &avgfreq[i]);
719 }
720
721 if (signal(SIGINT, signal_int_handler) == SIG_ERR)
722 {
723 fprintf(stderr, "failed to set signal int handler\n");
724 free(sum);
725 free(pxstat);
726 free(cxstat);
727 free(avgfreq);
728 return ;
729 }
730
731 if ( timeout > 0 )
732 {
733 if ( signal(SIGALRM, signal_int_handler) == SIG_ERR )
734 {
735 fprintf(stderr, "failed to set signal alarm handler\n");
736 free(sum);
737 free(pxstat);
738 free(cxstat);
739 free(avgfreq);
740 return ;
741 }
742 alarm(timeout);
743 }
744
745 printf("Start sampling, waiting for CTRL-C or SIGINT or SIGALARM signal ...\n");
746
747 pause();
748 }
749
calculate_activity_window(const xc_cppc_para_t * cppc,const char ** units)750 static unsigned int calculate_activity_window(const xc_cppc_para_t *cppc,
751 const char **units)
752 {
753 unsigned int mantissa = MASK_EXTR(cppc->activity_window,
754 XEN_CPPC_ACT_WINDOW_MANTISSA_MASK);
755 unsigned int exponent = MASK_EXTR(cppc->activity_window,
756 XEN_CPPC_ACT_WINDOW_EXPONENT_MASK);
757 unsigned int multiplier = 1;
758 unsigned int i;
759
760 /*
761 * SDM only states a 0 register is hardware selected, and doesn't mention
762 * a 0 mantissa with a non-0 exponent. Only special case a 0 register.
763 */
764 if ( cppc->activity_window == 0 )
765 {
766 *units = "hardware selected";
767
768 return 0;
769 }
770
771 if ( exponent >= 6 )
772 {
773 *units = "s";
774 exponent -= 6;
775 }
776 else if ( exponent >= 3 )
777 {
778 *units = "ms";
779 exponent -= 3;
780 }
781 else
782 *units = "us";
783
784 for ( i = 0; i < exponent; i++ )
785 multiplier *= 10;
786
787 return mantissa * multiplier;
788 }
789
790 /* print out parameters about cpu frequency */
print_cpufreq_para(int cpuid,struct xc_get_cpufreq_para * p_cpufreq)791 static void print_cpufreq_para(int cpuid, struct xc_get_cpufreq_para *p_cpufreq)
792 {
793 bool hwp = strcmp(p_cpufreq->scaling_driver, XEN_HWP_DRIVER_NAME) == 0;
794 int i;
795
796 printf("cpu id : %d\n", cpuid);
797
798 printf("affected_cpus :");
799 for ( i = 0; i < p_cpufreq->cpu_num; i++ )
800 printf(" %d", p_cpufreq->affected_cpus[i]);
801 printf("\n");
802
803 if ( hwp )
804 printf("cpuinfo frequency : base [%"PRIu32"] max [%"PRIu32"]\n",
805 p_cpufreq->cpuinfo_min_freq,
806 p_cpufreq->cpuinfo_max_freq);
807 else
808 printf("cpuinfo frequency : max [%u] min [%u] cur [%u]\n",
809 p_cpufreq->cpuinfo_max_freq,
810 p_cpufreq->cpuinfo_min_freq,
811 p_cpufreq->cpuinfo_cur_freq);
812
813 printf("scaling_driver : %s\n", p_cpufreq->scaling_driver);
814
815 if ( hwp )
816 {
817 const xc_cppc_para_t *cppc = &p_cpufreq->u.cppc_para;
818
819 printf("cppc variables :\n");
820 printf(" hardware limits : lowest [%"PRIu32"] lowest nonlinear [%"PRIu32"]\n",
821 cppc->lowest, cppc->lowest_nonlinear);
822 printf(" : nominal [%"PRIu32"] highest [%"PRIu32"]\n",
823 cppc->nominal, cppc->highest);
824 printf(" configured limits : min [%"PRIu32"] max [%"PRIu32"] energy perf [%"PRIu32"]\n",
825 cppc->minimum, cppc->maximum, cppc->energy_perf);
826
827 if ( cppc->features & XEN_SYSCTL_CPPC_FEAT_ACT_WINDOW )
828 {
829 unsigned int activity_window;
830 const char *units;
831
832 activity_window = calculate_activity_window(cppc, &units);
833 printf(" : activity_window [%"PRIu32" %s]\n",
834 activity_window, units);
835 }
836
837 printf(" : desired [%"PRIu32"%s]\n",
838 cppc->desired,
839 cppc->desired ? "" : " hw autonomous");
840 }
841 else
842 {
843 printf("scaling_avail_gov : %s\n",
844 p_cpufreq->scaling_available_governors);
845
846 printf("current_governor : %s\n", p_cpufreq->u.s.scaling_governor);
847 if ( !strncmp(p_cpufreq->u.s.scaling_governor,
848 "userspace", CPUFREQ_NAME_LEN) )
849 {
850 printf(" userspace specific :\n");
851 printf(" scaling_setspeed : %u\n",
852 p_cpufreq->u.s.u.userspace.scaling_setspeed);
853 }
854 else if ( !strncmp(p_cpufreq->u.s.scaling_governor,
855 "ondemand", CPUFREQ_NAME_LEN) )
856 {
857 printf(" ondemand specific :\n");
858 printf(" sampling_rate : max [%u] min [%u] cur [%u]\n",
859 p_cpufreq->u.s.u.ondemand.sampling_rate_max,
860 p_cpufreq->u.s.u.ondemand.sampling_rate_min,
861 p_cpufreq->u.s.u.ondemand.sampling_rate);
862 printf(" up_threshold : %u\n",
863 p_cpufreq->u.s.u.ondemand.up_threshold);
864 }
865
866 printf("scaling_avail_freq :");
867 for ( i = 0; i < p_cpufreq->freq_num; i++ )
868 if ( p_cpufreq->scaling_available_frequencies[i] ==
869 p_cpufreq->u.s.scaling_cur_freq )
870 printf(" *%d", p_cpufreq->scaling_available_frequencies[i]);
871 else
872 printf(" %d", p_cpufreq->scaling_available_frequencies[i]);
873 printf("\n");
874
875 printf("scaling frequency : max [%u] min [%u] cur [%u]\n",
876 p_cpufreq->u.s.scaling_max_freq,
877 p_cpufreq->u.s.scaling_min_freq,
878 p_cpufreq->u.s.scaling_cur_freq);
879 }
880
881 printf("turbo mode : %s\n",
882 p_cpufreq->turbo_enabled ? "enabled" : "disabled or n/a");
883 printf("\n");
884 }
885
886 /* show cpu frequency parameters information on CPU cpuid */
show_cpufreq_para_by_cpuid(xc_interface * xc_handle,int cpuid)887 static int show_cpufreq_para_by_cpuid(xc_interface *xc_handle, int cpuid)
888 {
889 int ret = 0;
890 struct xc_get_cpufreq_para cpufreq_para, *p_cpufreq = &cpufreq_para;
891
892 p_cpufreq->cpu_num = 0;
893 p_cpufreq->freq_num = 0;
894 p_cpufreq->gov_num = 0;
895 p_cpufreq->affected_cpus = NULL;
896 p_cpufreq->scaling_available_frequencies = NULL;
897 p_cpufreq->scaling_available_governors = NULL;
898 p_cpufreq->turbo_enabled = 0;
899
900 do
901 {
902 free(p_cpufreq->affected_cpus);
903 free(p_cpufreq->scaling_available_frequencies);
904 free(p_cpufreq->scaling_available_governors);
905
906 p_cpufreq->affected_cpus = NULL;
907 p_cpufreq->scaling_available_frequencies = NULL;
908 p_cpufreq->scaling_available_governors = NULL;
909
910 if (!(p_cpufreq->affected_cpus =
911 malloc(p_cpufreq->cpu_num * sizeof(uint32_t))))
912 {
913 fprintf(stderr,
914 "[CPU%d] failed to malloc for affected_cpus\n",
915 cpuid);
916 ret = -ENOMEM;
917 goto out;
918 }
919 if (!(p_cpufreq->scaling_available_frequencies =
920 malloc(p_cpufreq->freq_num * sizeof(uint32_t))))
921 {
922 fprintf(stderr,
923 "[CPU%d] failed to malloc for scaling_available_frequencies\n",
924 cpuid);
925 ret = -ENOMEM;
926 goto out;
927 }
928 if (p_cpufreq->gov_num &&
929 !(p_cpufreq->scaling_available_governors =
930 malloc(p_cpufreq->gov_num * CPUFREQ_NAME_LEN * sizeof(char))))
931 {
932 fprintf(stderr,
933 "[CPU%d] failed to malloc for scaling_available_governors\n",
934 cpuid);
935 ret = -ENOMEM;
936 goto out;
937 }
938
939 ret = xc_get_cpufreq_para(xc_handle, cpuid, p_cpufreq);
940 } while ( ret && errno == EAGAIN );
941
942 if ( ret == 0 )
943 print_cpufreq_para(cpuid, p_cpufreq);
944 else if ( errno == ENODEV )
945 {
946 ret = -ENODEV;
947 fprintf(stderr, "Xen cpufreq is not enabled!\n");
948 }
949 else
950 fprintf(stderr,
951 "[CPU%d] failed to get cpufreq parameter\n",
952 cpuid);
953
954 out:
955 free(p_cpufreq->scaling_available_governors);
956 free(p_cpufreq->scaling_available_frequencies);
957 free(p_cpufreq->affected_cpus);
958
959 return ret;
960 }
961
cpufreq_para_func(int argc,char * argv[])962 void cpufreq_para_func(int argc, char *argv[])
963 {
964 int cpuid = -1;
965
966 if ( argc > 0 )
967 parse_cpuid(argv[0], &cpuid);
968
969 if ( cpuid < 0 )
970 {
971 /* show cpu freqency information on all cpus */
972 int i;
973 for ( i = 0; i < max_cpu_nr; i++ )
974 if ( show_cpufreq_para_by_cpuid(xc_handle, i) == -ENODEV )
975 break;
976 }
977 else
978 show_cpufreq_para_by_cpuid(xc_handle, cpuid);
979 }
980
scaling_max_freq_func(int argc,char * argv[])981 void scaling_max_freq_func(int argc, char *argv[])
982 {
983 int cpuid = -1, freq = -1;
984
985 parse_cpuid_and_int(argc, argv, &cpuid, &freq, "frequency");
986
987 if ( cpuid < 0 )
988 {
989 int i;
990 for ( i = 0; i < max_cpu_nr; i++ )
991 if ( xc_set_cpufreq_para(xc_handle, i, SCALING_MAX_FREQ, freq) )
992 fprintf(stderr,
993 "[CPU%d] failed to set scaling max freq (%d - %s)\n",
994 i, errno, strerror(errno));
995 }
996 else
997 {
998 if ( xc_set_cpufreq_para(xc_handle, cpuid, SCALING_MAX_FREQ, freq) )
999 fprintf(stderr, "failed to set scaling max freq (%d - %s)\n",
1000 errno, strerror(errno));
1001 }
1002 }
1003
scaling_min_freq_func(int argc,char * argv[])1004 void scaling_min_freq_func(int argc, char *argv[])
1005 {
1006 int cpuid = -1, freq = -1;
1007
1008 parse_cpuid_and_int(argc, argv, &cpuid, &freq, "frequency");
1009
1010 if ( cpuid < 0 )
1011 {
1012 int i;
1013 for ( i = 0; i < max_cpu_nr; i++ )
1014 if ( xc_set_cpufreq_para(xc_handle, i, SCALING_MIN_FREQ, freq) )
1015 fprintf(stderr,
1016 "[CPU%d] failed to set scaling min freq (%d - %s)\n",
1017 i, errno, strerror(errno));
1018 }
1019 else
1020 {
1021 if ( xc_set_cpufreq_para(xc_handle, cpuid, SCALING_MIN_FREQ, freq) )
1022 fprintf(stderr, "failed to set scaling min freq (%d - %s)\n",
1023 errno, strerror(errno));
1024 }
1025 }
1026
scaling_speed_func(int argc,char * argv[])1027 void scaling_speed_func(int argc, char *argv[])
1028 {
1029 int cpuid = -1, speed = -1;
1030
1031 parse_cpuid_and_int(argc, argv, &cpuid, &speed, "speed");
1032
1033 if ( cpuid < 0 )
1034 {
1035 int i;
1036 for ( i = 0; i < max_cpu_nr; i++ )
1037 if ( xc_set_cpufreq_para(xc_handle, i, SCALING_SETSPEED, speed) )
1038 fprintf(stderr,
1039 "[CPU%d] failed to set scaling speed (%d - %s)\n",
1040 i, errno, strerror(errno));
1041 }
1042 else
1043 {
1044 if ( xc_set_cpufreq_para(xc_handle, cpuid, SCALING_SETSPEED, speed) )
1045 fprintf(stderr, "failed to set scaling speed (%d - %s)\n",
1046 errno, strerror(errno));
1047 }
1048 }
1049
scaling_sampling_rate_func(int argc,char * argv[])1050 void scaling_sampling_rate_func(int argc, char *argv[])
1051 {
1052 int cpuid = -1, rate = -1;
1053
1054 parse_cpuid_and_int(argc, argv, &cpuid, &rate, "rate");
1055
1056 if ( cpuid < 0 )
1057 {
1058 int i;
1059 for ( i = 0; i < max_cpu_nr; i++ )
1060 if ( xc_set_cpufreq_para(xc_handle, i, SAMPLING_RATE, rate) )
1061 fprintf(stderr,
1062 "[CPU%d] failed to set scaling sampling rate (%d - %s)\n",
1063 i, errno, strerror(errno));
1064 }
1065 else
1066 {
1067 if ( xc_set_cpufreq_para(xc_handle, cpuid, SAMPLING_RATE, rate) )
1068 fprintf(stderr, "failed to set scaling sampling rate (%d - %s)\n",
1069 errno, strerror(errno));
1070 }
1071 }
1072
scaling_up_threshold_func(int argc,char * argv[])1073 void scaling_up_threshold_func(int argc, char *argv[])
1074 {
1075 int cpuid = -1, threshold = -1;
1076
1077 parse_cpuid_and_int(argc, argv, &cpuid, &threshold, "threshold");
1078
1079 if ( cpuid < 0 )
1080 {
1081 int i;
1082 for ( i = 0; i < max_cpu_nr; i++ )
1083 if ( xc_set_cpufreq_para(xc_handle, i, UP_THRESHOLD, threshold) )
1084 fprintf(stderr,
1085 "[CPU%d] failed to set up scaling threshold (%d - %s)\n",
1086 i, errno, strerror(errno));
1087 }
1088 else
1089 {
1090 if ( xc_set_cpufreq_para(xc_handle, cpuid, UP_THRESHOLD, threshold) )
1091 fprintf(stderr, "failed to set up scaling threshold (%d - %s)\n",
1092 errno, strerror(errno));
1093 }
1094 }
1095
scaling_governor_func(int argc,char * argv[])1096 void scaling_governor_func(int argc, char *argv[])
1097 {
1098 int cpuid = -1;
1099 char *name;
1100
1101 if ( argc >= 2 )
1102 {
1103 parse_cpuid(argv[0], &cpuid);
1104 name = argv[1];
1105 }
1106 else if ( argc > 0 )
1107 name = argv[0];
1108 else
1109 {
1110 fprintf(stderr, "Missing argument(s)\n");
1111 exit(EINVAL);
1112 }
1113
1114 if ( cpuid < 0 )
1115 {
1116 int i;
1117 for ( i = 0; i < max_cpu_nr; i++ )
1118 if ( xc_set_cpufreq_gov(xc_handle, i, name) )
1119 fprintf(stderr, "[CPU%d] failed to set governor name (%d - %s)\n",
1120 i, errno, strerror(errno));
1121 }
1122 else
1123 {
1124 if ( xc_set_cpufreq_gov(xc_handle, cpuid, name) )
1125 fprintf(stderr, "failed to set governor name (%d - %s)\n",
1126 errno, strerror(errno));
1127 }
1128 }
1129
cpu_topology_func(int argc,char * argv[])1130 void cpu_topology_func(int argc, char *argv[])
1131 {
1132 xc_cputopo_t *cputopo = NULL;
1133 unsigned max_cpus = 0;
1134 int i, rc;
1135
1136 if ( xc_cputopoinfo(xc_handle, &max_cpus, NULL) != 0 )
1137 {
1138 rc = errno;
1139 fprintf(stderr, "failed to discover number of CPUs (%d - %s)\n",
1140 errno, strerror(errno));
1141 goto out;
1142 }
1143
1144 cputopo = calloc(max_cpus, sizeof(*cputopo));
1145 if ( cputopo == NULL )
1146 {
1147 rc = ENOMEM;
1148 fprintf(stderr, "failed to allocate hypercall buffers\n");
1149 goto out;
1150 }
1151
1152 if ( xc_cputopoinfo(xc_handle, &max_cpus, cputopo) )
1153 {
1154 rc = errno;
1155 fprintf(stderr, "Cannot get Xen CPU topology (%d - %s)\n",
1156 errno, strerror(errno));
1157 goto out;
1158 }
1159
1160 printf("CPU\tcore\tsocket\tnode\n");
1161 for ( i = 0; i < max_cpus; i++ )
1162 {
1163 if ( cputopo[i].core == XEN_INVALID_CORE_ID )
1164 continue;
1165 printf("CPU%d\t %d\t %d\t %d\n",
1166 i, cputopo[i].core, cputopo[i].socket, cputopo[i].node);
1167 }
1168 rc = 0;
1169 out:
1170 free(cputopo);
1171 if ( rc )
1172 exit(rc);
1173 }
1174
set_sched_smt_func(int argc,char * argv[])1175 void set_sched_smt_func(int argc, char *argv[])
1176 {
1177 int value;
1178
1179 if ( argc != 1 ) {
1180 fprintf(stderr, "Missing or invalid argument(s)\n");
1181 exit(EINVAL);
1182 }
1183
1184 if ( !strcasecmp(argv[0], "disable") )
1185 value = 0;
1186 else if ( !strcasecmp(argv[0], "enable") )
1187 value = 1;
1188 else
1189 {
1190 fprintf(stderr, "Invalid argument: %s\n", argv[0]);
1191 exit(EINVAL);
1192 }
1193
1194 if ( !xc_set_sched_opt_smt(xc_handle, value) )
1195 printf("%s sched_smt_power_savings succeeded\n", argv[0]);
1196 else
1197 fprintf(stderr, "%s sched_smt_power_savings failed (%d - %s)\n",
1198 argv[0], errno, strerror(errno));
1199 }
1200
set_vcpu_migration_delay_func(int argc,char * argv[])1201 void set_vcpu_migration_delay_func(int argc, char *argv[])
1202 {
1203 struct xen_sysctl_credit_schedule sparam;
1204 int value;
1205
1206 fprintf(stderr, "WARNING: using xenpm for this purpose is deprecated."
1207 " Check out `xl sched-credit -s -m DELAY'\n");
1208
1209 if ( argc != 1 || (value = atoi(argv[0])) < 0 ) {
1210 fprintf(stderr, "Missing or invalid argument(s)\n");
1211 exit(EINVAL);
1212 }
1213
1214 if ( xc_sched_credit_params_get(xc_handle, 0, &sparam) < 0 ) {
1215 fprintf(stderr, "getting Credit scheduler parameters failed\n");
1216 exit(EINVAL);
1217 }
1218 sparam.vcpu_migr_delay_us = value;
1219
1220 if ( !xc_sched_credit_params_set(xc_handle, 0, &sparam) )
1221 printf("set vcpu migration delay to %d us succeeded\n", value);
1222 else
1223 fprintf(stderr, "set vcpu migration delay failed (%d - %s)\n",
1224 errno, strerror(errno));
1225 }
1226
get_vcpu_migration_delay_func(int argc,char * argv[])1227 void get_vcpu_migration_delay_func(int argc, char *argv[])
1228 {
1229 struct xen_sysctl_credit_schedule sparam;
1230
1231 fprintf(stderr, "WARNING: using xenpm for this purpose is deprecated."
1232 " Check out `xl sched-credit -s'\n");
1233
1234 if ( argc )
1235 fprintf(stderr, "Ignoring argument(s)\n");
1236
1237 if ( !xc_sched_credit_params_get(xc_handle, 0, &sparam) )
1238 printf("Scheduler vcpu migration delay is %d us\n",
1239 sparam.vcpu_migr_delay_us);
1240 else
1241 fprintf(stderr,
1242 "Failed to get scheduler vcpu migration delay (%d - %s)\n",
1243 errno, strerror(errno));
1244 }
1245
set_max_cstate_func(int argc,char * argv[])1246 void set_max_cstate_func(int argc, char *argv[])
1247 {
1248 int value, subval = XEN_SYSCTL_CX_UNLIMITED;
1249 char buf[12];
1250
1251 if ( argc < 1 || argc > 2 ||
1252 (sscanf(argv[0], "%d", &value) == 1
1253 ? value < 0
1254 : (value = XEN_SYSCTL_CX_UNLIMITED, strcmp(argv[0], "unlimited"))) ||
1255 (argc == 2 &&
1256 (sscanf(argv[1], "%d", &subval) == 1
1257 ? subval < 0
1258 : (subval = XEN_SYSCTL_CX_UNLIMITED, strcmp(argv[1], "unlimited")))) )
1259 {
1260 fprintf(stderr, "Missing, excess, or invalid argument(s)\n");
1261 exit(EINVAL);
1262 }
1263
1264 snprintf(buf, ARRAY_SIZE(buf), "C%d", value);
1265
1266 if ( !xc_set_cpuidle_max_cstate(xc_handle, (uint32_t)value) )
1267 printf("max C-state set to %s\n", value >= 0 ? buf : argv[0]);
1268 else
1269 {
1270 fprintf(stderr, "Failed to set max C-state to %s (%d - %s)\n",
1271 value >= 0 ? buf : argv[0], errno, strerror(errno));
1272 return;
1273 }
1274
1275 if ( value != XEN_SYSCTL_CX_UNLIMITED )
1276 {
1277 snprintf(buf, ARRAY_SIZE(buf), "%d", subval);
1278
1279 if ( !xc_set_cpuidle_max_csubstate(xc_handle, (uint32_t)subval) )
1280 printf("max C-substate set to %s succeeded\n",
1281 subval >= 0 ? buf : "unlimited");
1282 else
1283 fprintf(stderr, "Failed to set max C-substate to %s (%d - %s)\n",
1284 subval >= 0 ? buf : "unlimited", errno, strerror(errno));
1285 }
1286 }
1287
enable_turbo_mode(int argc,char * argv[])1288 void enable_turbo_mode(int argc, char *argv[])
1289 {
1290 int cpuid = -1;
1291
1292 if ( argc > 0 )
1293 parse_cpuid(argv[0], &cpuid);
1294
1295 if ( cpuid < 0 )
1296 {
1297 /* enable turbo modes on all cpus,
1298 * only make effects on dbs governor */
1299 int i;
1300 for ( i = 0; i < max_cpu_nr; i++ )
1301 if ( xc_enable_turbo(xc_handle, i) )
1302 fprintf(stderr,
1303 "[CPU%d] failed to enable turbo mode (%d - %s)\n",
1304 i, errno, strerror(errno));
1305 }
1306 else if ( xc_enable_turbo(xc_handle, cpuid) )
1307 fprintf(stderr, "failed to enable turbo mode (%d - %s)\n",
1308 errno, strerror(errno));
1309 }
1310
disable_turbo_mode(int argc,char * argv[])1311 void disable_turbo_mode(int argc, char *argv[])
1312 {
1313 int cpuid = -1;
1314
1315 if ( argc > 0 )
1316 parse_cpuid(argv[0], &cpuid);
1317
1318 if ( cpuid < 0 )
1319 {
1320 /* disable turbo modes on all cpus,
1321 * only make effects on dbs governor */
1322 int i;
1323 for ( i = 0; i < max_cpu_nr; i++ )
1324 if ( xc_disable_turbo(xc_handle, i) )
1325 fprintf(stderr,
1326 "[CPU%d] failed to disable turbo mode (%d - %s)\n",
1327 i, errno, strerror(errno));
1328 }
1329 else if ( xc_disable_turbo(xc_handle, cpuid) )
1330 fprintf(stderr, "failed to disable turbo mode (%d - %s)\n",
1331 errno, strerror(errno));
1332 }
1333
1334 /*
1335 * Parse activity_window:NNN{us,ms,s} and validate range.
1336 *
1337 * Activity window is a 7bit mantissa (0-127) with a 3bit exponent (0-7) base
1338 * 10 in microseconds. So the range is 1 microsecond to 1270 seconds. A value
1339 * of 0 lets the hardware autonomously select the window.
1340 *
1341 * Return 0 on success
1342 * -1 on error
1343 */
parse_activity_window(xc_set_cppc_para_t * set_cppc,unsigned long u,const char * suffix)1344 static int parse_activity_window(xc_set_cppc_para_t *set_cppc, unsigned long u,
1345 const char *suffix)
1346 {
1347 unsigned int exponent = 0;
1348 unsigned int multiplier = 1;
1349
1350 if ( suffix && suffix[0] )
1351 {
1352 if ( strcmp(suffix, "s") == 0 )
1353 {
1354 multiplier = 1000 * 1000;
1355 exponent = 6;
1356 }
1357 else if ( strcmp(suffix, "ms") == 0 )
1358 {
1359 multiplier = 1000;
1360 exponent = 3;
1361 }
1362 else if ( strcmp(suffix, "us") != 0 )
1363 {
1364 fprintf(stderr, "invalid activity window units: \"%s\"\n", suffix);
1365
1366 return -1;
1367 }
1368 }
1369
1370 /* u * multipler > 1270 * 1000 * 1000 transformed to avoid overflow. */
1371 if ( u > 1270 * 1000 * 1000 / multiplier )
1372 {
1373 fprintf(stderr, "activity window is too large\n");
1374
1375 return -1;
1376 }
1377
1378 /* looking for 7 bits of mantissa and 3 bits of exponent */
1379 while ( u > 127 )
1380 {
1381 u += 5; /* Round up to mitigate truncation rounding down
1382 e.g. 128 -> 120 vs 128 -> 130. */
1383 u /= 10;
1384 exponent += 1;
1385 }
1386
1387 set_cppc->activity_window =
1388 MASK_INSR(exponent, XEN_CPPC_ACT_WINDOW_EXPONENT_MASK) |
1389 MASK_INSR(u, XEN_CPPC_ACT_WINDOW_MANTISSA_MASK);
1390 set_cppc->set_params |= XEN_SYSCTL_CPPC_SET_ACT_WINDOW;
1391
1392 return 0;
1393 }
1394
parse_cppc_opts(xc_set_cppc_para_t * set_cppc,int * cpuid,int argc,char * argv[])1395 static int parse_cppc_opts(xc_set_cppc_para_t *set_cppc, int *cpuid,
1396 int argc, char *argv[])
1397 {
1398 int i = 0;
1399
1400 if ( argc < 1 )
1401 {
1402 fprintf(stderr, "Missing arguments\n");
1403 return -1;
1404 }
1405
1406 if ( isdigit(argv[i][0]) )
1407 {
1408 if ( sscanf(argv[i], "%d", cpuid) != 1 || *cpuid < 0 )
1409 {
1410 fprintf(stderr, "Could not parse cpuid \"%s\"\n", argv[i]);
1411 return -1;
1412 }
1413
1414 i++;
1415 }
1416
1417 if ( i == argc )
1418 {
1419 fprintf(stderr, "Missing arguments\n");
1420 return -1;
1421 }
1422
1423 if ( strcasecmp(argv[i], "powersave") == 0 )
1424 {
1425 set_cppc->set_params = XEN_SYSCTL_CPPC_SET_PRESET_POWERSAVE;
1426 i++;
1427 }
1428 else if ( strcasecmp(argv[i], "performance") == 0 )
1429 {
1430 set_cppc->set_params = XEN_SYSCTL_CPPC_SET_PRESET_PERFORMANCE;
1431 i++;
1432 }
1433 else if ( strcasecmp(argv[i], "balance") == 0 )
1434 {
1435 set_cppc->set_params = XEN_SYSCTL_CPPC_SET_PRESET_BALANCE;
1436 i++;
1437 }
1438
1439 for ( ; i < argc; i++)
1440 {
1441 unsigned long val;
1442 char *param = argv[i];
1443 char *value;
1444 char *suffix;
1445 int ret;
1446
1447 value = strchr(param, ':');
1448 if ( value == NULL )
1449 {
1450 fprintf(stderr, "\"%s\" is an invalid cppc parameter\n", argv[i]);
1451 return -1;
1452 }
1453
1454 value[0] = '\0';
1455 value++;
1456
1457 errno = 0;
1458 val = strtoul(value, &suffix, 10);
1459 if ( (errno && val == ULONG_MAX) || value == suffix )
1460 {
1461 fprintf(stderr, "Could not parse number \"%s\"\n", value);
1462 return -1;
1463 }
1464
1465 if ( strncasecmp(param, "act-window", strlen(param)) == 0 )
1466 {
1467 ret = parse_activity_window(set_cppc, val, suffix);
1468 if (ret)
1469 return -1;
1470
1471 continue;
1472 }
1473
1474 if ( val > 255 )
1475 {
1476 fprintf(stderr, "\"%s\" value \"%lu\" is out of range\n", param,
1477 val);
1478 return -1;
1479 }
1480
1481 if ( suffix && suffix[0] )
1482 {
1483 fprintf(stderr, "Suffix \"%s\" is invalid\n", suffix);
1484 return -1;
1485 }
1486
1487 if ( strncasecmp(param, "minimum", MAX(2, strlen(param))) == 0 )
1488 {
1489 set_cppc->minimum = val;
1490 set_cppc->set_params |= XEN_SYSCTL_CPPC_SET_MINIMUM;
1491 }
1492 else if ( strncasecmp(param, "maximum", MAX(2, strlen(param))) == 0 )
1493 {
1494 set_cppc->maximum = val;
1495 set_cppc->set_params |= XEN_SYSCTL_CPPC_SET_MAXIMUM;
1496 }
1497 else if ( strncasecmp(param, "desired", strlen(param)) == 0 )
1498 {
1499 set_cppc->desired = val;
1500 set_cppc->set_params |= XEN_SYSCTL_CPPC_SET_DESIRED;
1501 }
1502 else if ( strncasecmp(param, "energy-perf", strlen(param)) == 0 )
1503 {
1504 set_cppc->energy_perf = val;
1505 set_cppc->set_params |= XEN_SYSCTL_CPPC_SET_ENERGY_PERF;
1506 }
1507 else
1508 {
1509 fprintf(stderr, "\"%s\" is an invalid parameter\n", param);
1510 return -1;
1511 }
1512 }
1513
1514 if ( set_cppc->set_params == 0 )
1515 {
1516 fprintf(stderr, "No parameters set in request\n");
1517 return -1;
1518 }
1519
1520 return 0;
1521 }
1522
cppc_set_func(int argc,char * argv[])1523 static void cppc_set_func(int argc, char *argv[])
1524 {
1525 xc_set_cppc_para_t set_cppc = {};
1526 unsigned int max_cpuid = max_cpu_nr;
1527 int cpuid = -1;
1528 unsigned int i = 0;
1529 uint32_t set_params;
1530
1531 if ( parse_cppc_opts(&set_cppc, &cpuid, argc, argv) )
1532 exit(EINVAL);
1533
1534 if ( cpuid != -1 )
1535 {
1536 i = cpuid;
1537 max_cpuid = i + 1;
1538 }
1539
1540 set_params = set_cppc.set_params;
1541 for ( ; i < max_cpuid; i++ ) {
1542 if ( xc_set_cpufreq_cppc(xc_handle, i, &set_cppc) )
1543 fprintf(stderr, "[CPU%d] failed to set cppc params (%d - %s)\n",
1544 i, errno, strerror(errno));
1545 }
1546
1547 if ( (set_params ^ set_cppc.set_params) & XEN_SYSCTL_CPPC_SET_ACT_WINDOW )
1548 printf("Activity window not supported and omitted\n");
1549 }
1550
1551 struct {
1552 const char *name;
1553 void (*function)(int argc, char *argv[]);
1554 } main_options[] = {
1555 { "help", help_func },
1556 { "get-cpuidle-states", cxstat_func },
1557 { "get-cpufreq-states", pxstat_func },
1558 { "get-cpufreq-average", cpufreq_func },
1559 { "start", start_gather_func },
1560 { "get-cpufreq-para", cpufreq_para_func },
1561 { "set-cpufreq-cppc", cppc_set_func },
1562 { "set-scaling-maxfreq", scaling_max_freq_func },
1563 { "set-scaling-minfreq", scaling_min_freq_func },
1564 { "set-scaling-governor", scaling_governor_func },
1565 { "set-scaling-speed", scaling_speed_func },
1566 { "set-sampling-rate", scaling_sampling_rate_func },
1567 { "set-up-threshold", scaling_up_threshold_func },
1568 { "get-cpu-topology", cpu_topology_func},
1569 { "set-sched-smt", set_sched_smt_func},
1570 { "get-vcpu-migration-delay", get_vcpu_migration_delay_func},
1571 { "set-vcpu-migration-delay", set_vcpu_migration_delay_func},
1572 { "set-max-cstate", set_max_cstate_func},
1573 { "enable-turbo-mode", enable_turbo_mode },
1574 { "disable-turbo-mode", disable_turbo_mode },
1575 };
1576
main(int argc,char * argv[])1577 int main(int argc, char *argv[])
1578 {
1579 int i, ret = 0;
1580 xc_physinfo_t physinfo;
1581 int nr_matches = 0;
1582 int matches_main_options[ARRAY_SIZE(main_options)];
1583
1584 if ( argc < 2 )
1585 {
1586 show_help();
1587 return 0;
1588 }
1589
1590 xc_handle = xc_interface_open(0,0,0);
1591 if ( !xc_handle )
1592 {
1593 fprintf(stderr, "failed to get the handler\n");
1594 return EIO;
1595 }
1596
1597 ret = xc_physinfo(xc_handle, &physinfo);
1598 if ( ret )
1599 {
1600 ret = errno;
1601 fprintf(stderr, "failed to get processor information (%d - %s)\n",
1602 ret, strerror(ret));
1603 xc_interface_close(xc_handle);
1604 return ret;
1605 }
1606 max_cpu_nr = physinfo.max_cpu_id + 1;
1607
1608 /* calculate how many options match with user's input */
1609 for ( i = 0; i < ARRAY_SIZE(main_options); i++ )
1610 if ( !strncmp(main_options[i].name, argv[1], strlen(argv[1])) )
1611 matches_main_options[nr_matches++] = i;
1612
1613 if ( nr_matches > 1 )
1614 {
1615 fprintf(stderr, "Ambiguous options: ");
1616 for ( i = 0; i < nr_matches; i++ )
1617 fprintf(stderr, " %s", main_options[matches_main_options[i]].name);
1618 fprintf(stderr, "\n");
1619 ret = EINVAL;
1620 }
1621 else if ( nr_matches == 1 )
1622 /* dispatch to the corresponding function handler */
1623 main_options[matches_main_options[0]].function(argc - 2, argv + 2);
1624 else
1625 {
1626 show_help();
1627 ret = EINVAL;
1628 }
1629
1630 xc_interface_close(xc_handle);
1631 return ret;
1632 }
1633
1634