debuggers.hg

view tools/misc/xenpm.c @ 20954:a06e9def02bb

xenpm: Allow user to enable/disable dbs governor turbo mode.

Signed-off-by: Lu Guanqun <guanqun.lu@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Feb 08 08:48:40 2010 +0000 (2010-02-08)
parents 5966b71195b4
children 3ffdb094c2c0 6c3db6c83a02
line source
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, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 */
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <getopt.h>
24 #include <errno.h>
25 #include <signal.h>
27 #include <xenctrl.h>
28 #include <inttypes.h>
29 #include <sys/time.h>
31 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
33 static int xc_fd;
34 static int max_cpu_nr;
36 /* help message */
37 void show_help(void)
38 {
39 fprintf(stderr,
40 "xen power management control tool\n\n"
41 "usage: xenpm <command> [args]\n\n"
42 "xenpm command list:\n\n"
43 " get-cpuidle-states [cpuid] list cpu idle info of CPU <cpuid> or all\n"
44 " get-cpufreq-states [cpuid] list cpu freq info of CPU <cpuid> or all\n"
45 " get-cpufreq-para [cpuid] list cpu freq parameter of CPU <cpuid> or all\n"
46 " set-scaling-maxfreq [cpuid] <HZ> set max cpu frequency <HZ> on CPU <cpuid>\n"
47 " or all CPUs\n"
48 " set-scaling-minfreq [cpuid] <HZ> set min cpu frequency <HZ> on CPU <cpuid>\n"
49 " or all CPUs\n"
50 " set-scaling-speed [cpuid] <num> set scaling speed on CPU <cpuid> or all\n"
51 " it is used in userspace governor.\n"
52 " set-scaling-governor [cpuid] <gov> set scaling governor on CPU <cpuid> or all\n"
53 " as userspace/performance/powersave/ondemand\n"
54 " set-sampling-rate [cpuid] <num> set sampling rate on CPU <cpuid> or all\n"
55 " it is used in ondemand governor.\n"
56 " set-up-threshold [cpuid] <num> set up threshold on CPU <cpuid> or all\n"
57 " it is used in ondemand governor.\n"
58 " get-cpu-topology get thread/core/socket topology info\n"
59 " set-sched-smt enable|disable enable/disable scheduler smt power saving\n"
60 " set-vcpu-migration-delay <num> set scheduler vcpu migration delay in us\n"
61 " get-vcpu-migration-delay get scheduler vcpu migration delay\n"
62 " set-max-cstate <num> set the C-State limitation (<num> >= 0)\n"
63 " start [seconds] start collect Cx/Px statistics,\n"
64 " output after CTRL-C or SIGINT or several seconds.\n"
65 " enable-turbo-mode [cpuid] enable Turbo Mode in DBS governor.\n"
66 " disable-turbo-mode [cpuid] disable Turbo Mode in DBS governor.\n"
67 );
68 }
69 /* wrapper function */
70 void help_func(int argc, char *argv[])
71 {
72 show_help();
73 }
75 static void print_cxstat(int cpuid, struct xc_cx_stat *cxstat)
76 {
77 int i;
79 printf("cpu id : %d\n", cpuid);
80 printf("total C-states : %d\n", cxstat->nr);
81 printf("idle time(ms) : %"PRIu64"\n",
82 cxstat->idle_time/1000000UL);
83 for ( i = 0; i < cxstat->nr; i++ )
84 {
85 printf("C%d : transition [%020"PRIu64"]\n",
86 i, cxstat->triggers[i]);
87 printf(" residency [%020"PRIu64" ms]\n",
88 cxstat->residencies[i]/1000000UL);
89 }
90 printf("\n");
91 }
93 /* show cpu idle information on CPU cpuid */
94 static int get_cxstat_by_cpuid(int xc_fd, int cpuid, struct xc_cx_stat *cxstat)
95 {
96 int ret = 0;
97 int max_cx_num = 0;
99 ret = xc_pm_get_max_cx(xc_fd, cpuid, &max_cx_num);
100 if ( ret )
101 return errno;
103 if ( !cxstat )
104 return -EINVAL;
106 cxstat->triggers = malloc(max_cx_num * sizeof(uint64_t));
107 if ( !cxstat->triggers )
108 return -ENOMEM;
109 cxstat->residencies = malloc(max_cx_num * sizeof(uint64_t));
110 if ( !cxstat->residencies )
111 {
112 free(cxstat->triggers);
113 return -ENOMEM;
114 }
116 ret = xc_pm_get_cxstat(xc_fd, cpuid, cxstat);
117 if( ret )
118 {
119 int temp = errno;
120 free(cxstat->triggers);
121 free(cxstat->residencies);
122 cxstat->triggers = NULL;
123 cxstat->residencies = NULL;
124 return temp;
125 }
127 return 0;
128 }
130 static int show_max_cstate(int xc_fd)
131 {
132 int ret = 0;
133 uint32_t value;
135 if ( (ret = xc_get_cpuidle_max_cstate(xc_fd, &value)) )
136 return ret;
138 printf("Max C-state: C%d\n\n", value);
139 return 0;
140 }
142 static int show_cxstat_by_cpuid(int xc_fd, int cpuid)
143 {
144 int ret = 0;
145 struct xc_cx_stat cxstatinfo;
147 ret = get_cxstat_by_cpuid(xc_fd, cpuid, &cxstatinfo);
148 if ( ret )
149 return ret;
151 print_cxstat(cpuid, &cxstatinfo);
153 free(cxstatinfo.triggers);
154 free(cxstatinfo.residencies);
155 return 0;
156 }
158 void cxstat_func(int argc, char *argv[])
159 {
160 int cpuid = -1;
162 if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
163 cpuid = -1;
165 if ( cpuid >= max_cpu_nr )
166 cpuid = -1;
168 show_max_cstate(xc_fd);
170 if ( cpuid < 0 )
171 {
172 /* show cxstates on all cpus */
173 int i;
174 for ( i = 0; i < max_cpu_nr; i++ )
175 if ( show_cxstat_by_cpuid(xc_fd, i) == -ENODEV )
176 break;
177 }
178 else
179 show_cxstat_by_cpuid(xc_fd, cpuid);
180 }
182 static void print_pxstat(int cpuid, struct xc_px_stat *pxstat)
183 {
184 int i;
186 printf("cpu id : %d\n", cpuid);
187 printf("total P-states : %d\n", pxstat->total);
188 printf("usable P-states : %d\n", pxstat->usable);
189 printf("current frequency : %"PRIu64" MHz\n",
190 pxstat->pt[pxstat->cur].freq);
191 for ( i = 0; i < pxstat->total; i++ )
192 {
193 if ( pxstat->cur == i )
194 printf("*P%d", i);
195 else
196 printf("P%d ", i);
197 printf(" : freq [%04"PRIu64" MHz]\n",
198 pxstat->pt[i].freq);
199 printf(" transition [%020"PRIu64"]\n",
200 pxstat->pt[i].count);
201 printf(" residency [%020"PRIu64" ms]\n",
202 pxstat->pt[i].residency/1000000UL);
203 }
204 printf("\n");
205 }
207 /* show cpu frequency information on CPU cpuid */
208 static int get_pxstat_by_cpuid(int xc_fd, int cpuid, struct xc_px_stat *pxstat)
209 {
210 int ret = 0;
211 int max_px_num = 0;
213 ret = xc_pm_get_max_px(xc_fd, cpuid, &max_px_num);
214 if ( ret )
215 return errno;
217 if ( !pxstat)
218 return -EINVAL;
220 pxstat->trans_pt = malloc(max_px_num * max_px_num *
221 sizeof(uint64_t));
222 if ( !pxstat->trans_pt )
223 return -ENOMEM;
224 pxstat->pt = malloc(max_px_num * sizeof(struct xc_px_val));
225 if ( !pxstat->pt )
226 {
227 free(pxstat->trans_pt);
228 return -ENOMEM;
229 }
231 ret = xc_pm_get_pxstat(xc_fd, cpuid, pxstat);
232 if( ret )
233 {
234 int temp = errno;
235 free(pxstat->trans_pt);
236 free(pxstat->pt);
237 pxstat->trans_pt = NULL;
238 pxstat->pt = NULL;
239 return temp;
240 }
242 return 0;
243 }
245 /* show cpu actual average freq information on CPU cpuid */
246 static int get_avgfreq_by_cpuid(int xc_fd, int cpuid, int *avgfreq)
247 {
248 int ret = 0;
250 ret = xc_get_cpufreq_avgfreq(xc_fd, cpuid, avgfreq);
251 if ( ret )
252 {
253 return errno;
254 }
256 return 0;
257 }
259 static int show_pxstat_by_cpuid(int xc_fd, int cpuid)
260 {
261 int ret = 0;
262 struct xc_px_stat pxstatinfo;
264 ret = get_pxstat_by_cpuid(xc_fd, cpuid, &pxstatinfo);
265 if ( ret )
266 return ret;
268 print_pxstat(cpuid, &pxstatinfo);
270 free(pxstatinfo.trans_pt);
271 free(pxstatinfo.pt);
272 return 0;
273 }
275 void pxstat_func(int argc, char *argv[])
276 {
277 int cpuid = -1;
279 if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
280 cpuid = -1;
282 if ( cpuid >= max_cpu_nr )
283 cpuid = -1;
285 if ( cpuid < 0 )
286 {
287 /* show pxstates on all cpus */
288 int i;
289 for ( i = 0; i < max_cpu_nr; i++ )
290 if ( show_pxstat_by_cpuid(xc_fd, i) == -ENODEV )
291 break;
292 }
293 else
294 show_pxstat_by_cpuid(xc_fd, cpuid);
295 }
297 static uint64_t usec_start, usec_end;
298 static struct xc_cx_stat *cxstat, *cxstat_start, *cxstat_end;
299 static struct xc_px_stat *pxstat, *pxstat_start, *pxstat_end;
300 static int *avgfreq;
301 static uint64_t *sum, *sum_cx, *sum_px;
303 static void signal_int_handler(int signo)
304 {
305 int i, j;
306 struct timeval tv;
307 int cx_cap = 0, px_cap = 0;
309 if ( gettimeofday(&tv, NULL) == -1 )
310 {
311 fprintf(stderr, "failed to get timeofday\n");
312 return ;
313 }
314 usec_end = tv.tv_sec * 1000000UL + tv.tv_usec;
316 if ( get_cxstat_by_cpuid(xc_fd, 0, NULL) != -ENODEV )
317 {
318 cx_cap = 1;
319 for ( i = 0; i < max_cpu_nr; i++ )
320 if ( !get_cxstat_by_cpuid(xc_fd, i, &cxstat_end[i]) )
321 for ( j = 0; j < cxstat_end[i].nr; j++ )
322 sum_cx[i] += cxstat_end[i].residencies[j] -
323 cxstat_start[i].residencies[j];
324 }
326 if ( get_pxstat_by_cpuid(xc_fd, 0, NULL) != -ENODEV )
327 {
328 px_cap = 1;
329 for ( i = 0; i < max_cpu_nr; i++ )
330 if ( !get_pxstat_by_cpuid(xc_fd, i , &pxstat_end[i]) )
331 for ( j = 0; j < pxstat_end[i].total; j++ )
332 sum_px[i] += pxstat_end[i].pt[j].residency -
333 pxstat_start[i].pt[j].residency;
334 }
336 for ( i = 0; i < max_cpu_nr; i++ )
337 get_avgfreq_by_cpuid(xc_fd, i, &avgfreq[i]);
339 printf("Elapsed time (ms): %"PRIu64"\n", (usec_end - usec_start) / 1000UL);
340 for ( i = 0; i < max_cpu_nr; i++ )
341 {
342 uint64_t res, triggers;
343 double avg_res;
345 printf("\nCPU%d:\tResidency(ms)\t\tAvg Res(ms)\n",i);
346 if ( cx_cap && sum_cx[i] > 0 )
347 {
348 for ( j = 0; j < cxstat_end[i].nr; j++ )
349 {
350 res = cxstat_end[i].residencies[j] -
351 cxstat_start[i].residencies[j];
352 triggers = cxstat_end[i].triggers[j] -
353 cxstat_start[i].triggers[j];
354 avg_res = (triggers==0) ? 0: (double)res/triggers/1000000.0;
355 printf(" C%d\t%"PRIu64"\t(%5.2f%%)\t%.2f\n", j, res/1000000UL,
356 100 * res / (double)sum_cx[i], avg_res );
357 }
358 printf("\n");
359 }
360 if ( px_cap && sum_px[i]>0 )
361 {
362 for ( j = 0; j < pxstat_end[i].total; j++ )
363 {
364 res = pxstat_end[i].pt[j].residency -
365 pxstat_start[i].pt[j].residency;
366 printf(" P%d\t%"PRIu64"\t(%5.2f%%)\n", j,
367 res / 1000000UL, 100UL * res / (double)sum_px[i]);
368 }
369 }
370 printf(" Avg freq\t%d\tKHz\n", avgfreq[i]);
371 }
373 /* some clean up and then exits */
374 for ( i = 0; i < 2 * max_cpu_nr; i++ )
375 {
376 free(cxstat[i].triggers);
377 free(cxstat[i].residencies);
378 free(pxstat[i].trans_pt);
379 free(pxstat[i].pt);
380 }
381 free(cxstat);
382 free(pxstat);
383 free(sum);
384 free(avgfreq);
385 xc_interface_close(xc_fd);
386 exit(0);
387 }
389 void start_gather_func(int argc, char *argv[])
390 {
391 int i;
392 struct timeval tv;
393 int timeout = 0;
395 if ( argc == 1 )
396 {
397 sscanf(argv[0], "%d", &timeout);
398 if ( timeout <= 0 )
399 fprintf(stderr, "failed to set timeout seconds, falling back...\n");
400 else
401 printf("Timeout set to %d seconds\n", timeout);
402 }
404 if ( gettimeofday(&tv, NULL) == -1 )
405 {
406 fprintf(stderr, "failed to get timeofday\n");
407 return ;
408 }
409 usec_start = tv.tv_sec * 1000000UL + tv.tv_usec;
411 sum = malloc(sizeof(uint64_t) * 2 * max_cpu_nr);
412 if ( sum == NULL )
413 return ;
414 cxstat = malloc(sizeof(struct xc_cx_stat) * 2 * max_cpu_nr);
415 if ( cxstat == NULL )
416 {
417 free(sum);
418 return ;
419 }
420 pxstat = malloc(sizeof(struct xc_px_stat) * 2 * max_cpu_nr);
421 if ( pxstat == NULL )
422 {
423 free(sum);
424 free(cxstat);
425 return ;
426 }
427 avgfreq = malloc(sizeof(int) * max_cpu_nr);
428 if ( avgfreq == NULL )
429 {
430 free(sum);
431 free(cxstat);
432 free(pxstat);
433 return ;
434 }
435 memset(sum, 0, sizeof(uint64_t) * 2 * max_cpu_nr);
436 memset(cxstat, 0, sizeof(struct xc_cx_stat) * 2 * max_cpu_nr);
437 memset(pxstat, 0, sizeof(struct xc_px_stat) * 2 * max_cpu_nr);
438 memset(avgfreq, 0, sizeof(int) * max_cpu_nr);
439 sum_cx = sum;
440 sum_px = sum + max_cpu_nr;
441 cxstat_start = cxstat;
442 cxstat_end = cxstat + max_cpu_nr;
443 pxstat_start = pxstat;
444 pxstat_end = pxstat + max_cpu_nr;
446 if ( get_cxstat_by_cpuid(xc_fd, 0, NULL) == -ENODEV &&
447 get_pxstat_by_cpuid(xc_fd, 0, NULL) == -ENODEV )
448 {
449 fprintf(stderr, "Xen cpu idle and frequency is disabled!\n");
450 return ;
451 }
453 for ( i = 0; i < max_cpu_nr; i++ )
454 {
455 get_cxstat_by_cpuid(xc_fd, i, &cxstat_start[i]);
456 get_pxstat_by_cpuid(xc_fd, i, &pxstat_start[i]);
457 get_avgfreq_by_cpuid(xc_fd, i, &avgfreq[i]);
458 }
460 if (signal(SIGINT, signal_int_handler) == SIG_ERR)
461 {
462 fprintf(stderr, "failed to set signal int handler\n");
463 free(sum);
464 free(pxstat);
465 free(cxstat);
466 free(avgfreq);
467 return ;
468 }
470 if ( timeout > 0 )
471 {
472 if ( signal(SIGALRM, signal_int_handler) == SIG_ERR )
473 {
474 fprintf(stderr, "failed to set signal alarm handler\n");
475 free(sum);
476 free(pxstat);
477 free(cxstat);
478 free(avgfreq);
479 return ;
480 }
481 alarm(timeout);
482 }
484 printf("Start sampling, waiting for CTRL-C or SIGINT or SIGALARM signal ...\n");
486 pause();
487 }
489 /* print out parameters about cpu frequency */
490 static void print_cpufreq_para(int cpuid, struct xc_get_cpufreq_para *p_cpufreq)
491 {
492 int i;
494 printf("cpu id : %d\n", cpuid);
496 printf("affected_cpus :");
497 for ( i = 0; i < p_cpufreq->cpu_num; i++ )
498 if ( i == cpuid )
499 printf(" *%d", p_cpufreq->affected_cpus[i]);
500 else
501 printf(" %d", p_cpufreq->affected_cpus[i]);
502 printf("\n");
504 printf("cpuinfo frequency : max [%u] min [%u] cur [%u]\n",
505 p_cpufreq->cpuinfo_max_freq,
506 p_cpufreq->cpuinfo_min_freq,
507 p_cpufreq->cpuinfo_cur_freq);
509 printf("scaling_driver : %s\n", p_cpufreq->scaling_driver);
511 printf("scaling_avail_gov : %s\n",
512 p_cpufreq->scaling_available_governors);
514 printf("current_governor : %s\n", p_cpufreq->scaling_governor);
515 if ( !strncmp(p_cpufreq->scaling_governor,
516 "userspace", CPUFREQ_NAME_LEN) )
517 {
518 printf(" userspace specific :\n");
519 printf(" scaling_setspeed : %u\n",
520 p_cpufreq->u.userspace.scaling_setspeed);
521 }
522 else if ( !strncmp(p_cpufreq->scaling_governor,
523 "ondemand", CPUFREQ_NAME_LEN) )
524 {
525 printf(" ondemand specific :\n");
526 printf(" sampling_rate : max [%u] min [%u] cur [%u]\n",
527 p_cpufreq->u.ondemand.sampling_rate_max,
528 p_cpufreq->u.ondemand.sampling_rate_min,
529 p_cpufreq->u.ondemand.sampling_rate);
530 printf(" up_threshold : %u\n",
531 p_cpufreq->u.ondemand.up_threshold);
532 printf(" turbo mode : %s\n",
533 p_cpufreq->u.ondemand.turbo_enabled ? "enabled" : "disabled");
534 }
536 printf("scaling_avail_freq :");
537 for ( i = 0; i < p_cpufreq->freq_num; i++ )
538 if ( p_cpufreq->scaling_available_frequencies[i] ==
539 p_cpufreq->scaling_cur_freq )
540 printf(" *%d", p_cpufreq->scaling_available_frequencies[i]);
541 else
542 printf(" %d", p_cpufreq->scaling_available_frequencies[i]);
543 printf("\n");
545 printf("scaling frequency : max [%u] min [%u] cur [%u]\n",
546 p_cpufreq->scaling_max_freq,
547 p_cpufreq->scaling_min_freq,
548 p_cpufreq->scaling_cur_freq);
549 printf("\n");
550 }
552 /* show cpu frequency parameters information on CPU cpuid */
553 static int show_cpufreq_para_by_cpuid(int xc_fd, int cpuid)
554 {
555 int ret = 0;
556 struct xc_get_cpufreq_para cpufreq_para, *p_cpufreq = &cpufreq_para;
558 p_cpufreq->cpu_num = 0;
559 p_cpufreq->freq_num = 0;
560 p_cpufreq->gov_num = 0;
561 p_cpufreq->affected_cpus = NULL;
562 p_cpufreq->scaling_available_frequencies = NULL;
563 p_cpufreq->scaling_available_governors = NULL;
565 do
566 {
567 free(p_cpufreq->affected_cpus);
568 free(p_cpufreq->scaling_available_frequencies);
569 free(p_cpufreq->scaling_available_governors);
571 p_cpufreq->affected_cpus = NULL;
572 p_cpufreq->scaling_available_frequencies = NULL;
573 p_cpufreq->scaling_available_governors = NULL;
575 if (!(p_cpufreq->affected_cpus =
576 malloc(p_cpufreq->cpu_num * sizeof(uint32_t))))
577 {
578 fprintf(stderr,
579 "[CPU%d] failed to malloc for affected_cpus\n",
580 cpuid);
581 ret = -ENOMEM;
582 goto out;
583 }
584 if (!(p_cpufreq->scaling_available_frequencies =
585 malloc(p_cpufreq->freq_num * sizeof(uint32_t))))
586 {
587 fprintf(stderr,
588 "[CPU%d] failed to malloc for scaling_available_frequencies\n",
589 cpuid);
590 ret = -ENOMEM;
591 goto out;
592 }
593 if (!(p_cpufreq->scaling_available_governors =
594 malloc(p_cpufreq->gov_num * CPUFREQ_NAME_LEN * sizeof(char))))
595 {
596 fprintf(stderr,
597 "[CPU%d] failed to malloc for scaling_available_governors\n",
598 cpuid);
599 ret = -ENOMEM;
600 goto out;
601 }
603 ret = xc_get_cpufreq_para(xc_fd, cpuid, p_cpufreq);
604 } while ( ret && errno == EAGAIN );
606 if ( ret == 0 )
607 print_cpufreq_para(cpuid, p_cpufreq);
608 else if ( errno == ENODEV )
609 {
610 ret = -ENODEV;
611 fprintf(stderr, "Xen cpufreq is not enabled!\n");
612 }
613 else
614 fprintf(stderr,
615 "[CPU%d] failed to get cpufreq parameter\n",
616 cpuid);
618 out:
619 free(p_cpufreq->scaling_available_governors);
620 free(p_cpufreq->scaling_available_frequencies);
621 free(p_cpufreq->affected_cpus);
623 return ret;
624 }
626 void cpufreq_para_func(int argc, char *argv[])
627 {
628 int cpuid = -1;
630 if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
631 cpuid = -1;
633 if ( cpuid >= max_cpu_nr )
634 cpuid = -1;
636 if ( cpuid < 0 )
637 {
638 /* show cpu freqency information on all cpus */
639 int i;
640 for ( i = 0; i < max_cpu_nr; i++ )
641 if ( show_cpufreq_para_by_cpuid(xc_fd, i) == -ENODEV )
642 break;
643 }
644 else
645 show_cpufreq_para_by_cpuid(xc_fd, cpuid);
646 }
648 void scaling_max_freq_func(int argc, char *argv[])
649 {
650 int cpuid = -1, freq = -1;
652 if ( (argc >= 2 && (sscanf(argv[1], "%d", &freq) != 1 ||
653 sscanf(argv[0], "%d", &cpuid) != 1)) ||
654 (argc == 1 && sscanf(argv[0], "%d", &freq) != 1 ) ||
655 argc == 0 )
656 {
657 fprintf(stderr, "failed to set scaling max freq\n");
658 return ;
659 }
661 if ( cpuid < 0 )
662 {
663 int i;
664 for ( i = 0; i < max_cpu_nr; i++ )
665 if ( xc_set_cpufreq_para(xc_fd, i, SCALING_MAX_FREQ, freq) )
666 fprintf(stderr, "[CPU%d] failed to set scaling max freq\n", i);
667 }
668 else
669 {
670 if ( xc_set_cpufreq_para(xc_fd, cpuid, SCALING_MAX_FREQ, freq) )
671 fprintf(stderr, "failed to set scaling max freq\n");
672 }
673 }
675 void scaling_min_freq_func(int argc, char *argv[])
676 {
677 int cpuid = -1, freq = -1;
679 if ( (argc >= 2 && (sscanf(argv[1], "%d", &freq) != 1 ||
680 sscanf(argv[0], "%d", &cpuid) != 1) ) ||
681 (argc == 1 && sscanf(argv[0], "%d", &freq) != 1 ) ||
682 argc == 0 )
683 {
684 fprintf(stderr, "failed to set scaling min freq\n");
685 return ;
686 }
688 if ( cpuid < 0 )
689 {
690 int i;
691 for ( i = 0; i < max_cpu_nr; i++ )
692 if ( xc_set_cpufreq_para(xc_fd, i, SCALING_MIN_FREQ, freq) )
693 fprintf(stderr, "[CPU%d] failed to set scaling min freq\n", i);
694 }
695 else
696 {
697 if ( xc_set_cpufreq_para(xc_fd, cpuid, SCALING_MIN_FREQ, freq) )
698 fprintf(stderr, "failed to set scaling min freq\n");
699 }
700 }
702 void scaling_speed_func(int argc, char *argv[])
703 {
704 int cpuid = -1, speed = -1;
706 if ( (argc >= 2 && (sscanf(argv[1], "%d", &speed) != 1 ||
707 sscanf(argv[0], "%d", &cpuid) != 1) ) ||
708 (argc == 1 && sscanf(argv[0], "%d", &speed) != 1 ) ||
709 argc == 0 )
710 {
711 fprintf(stderr, "failed to set scaling speed\n");
712 return ;
713 }
715 if ( cpuid < 0 )
716 {
717 int i;
718 for ( i = 0; i < max_cpu_nr; i++ )
719 if ( xc_set_cpufreq_para(xc_fd, i, SCALING_SETSPEED, speed) )
720 fprintf(stderr, "[CPU%d] failed to set scaling speed\n", i);
721 }
722 else
723 {
724 if ( xc_set_cpufreq_para(xc_fd, cpuid, SCALING_SETSPEED, speed) )
725 fprintf(stderr, "failed to set scaling speed\n");
726 }
727 }
729 void scaling_sampling_rate_func(int argc, char *argv[])
730 {
731 int cpuid = -1, rate = -1;
733 if ( (argc >= 2 && (sscanf(argv[1], "%d", &rate) != 1 ||
734 sscanf(argv[0], "%d", &cpuid) != 1) ) ||
735 (argc == 1 && sscanf(argv[0], "%d", &rate) != 1 ) ||
736 argc == 0 )
737 {
738 fprintf(stderr, "failed to set scaling sampling rate\n");
739 return ;
740 }
742 if ( cpuid < 0 )
743 {
744 int i;
745 for ( i = 0; i < max_cpu_nr; i++ )
746 if ( xc_set_cpufreq_para(xc_fd, i, SAMPLING_RATE, rate) )
747 fprintf(stderr,
748 "[CPU%d] failed to set scaling sampling rate\n", i);
749 }
750 else
751 {
752 if ( xc_set_cpufreq_para(xc_fd, cpuid, SAMPLING_RATE, rate) )
753 fprintf(stderr, "failed to set scaling sampling rate\n");
754 }
755 }
757 void scaling_up_threshold_func(int argc, char *argv[])
758 {
759 int cpuid = -1, threshold = -1;
761 if ( (argc >= 2 && (sscanf(argv[1], "%d", &threshold) != 1 ||
762 sscanf(argv[0], "%d", &cpuid) != 1) ) ||
763 (argc == 1 && sscanf(argv[0], "%d", &threshold) != 1 ) ||
764 argc == 0 )
765 {
766 fprintf(stderr, "failed to set up scaling threshold\n");
767 return ;
768 }
770 if ( cpuid < 0 )
771 {
772 int i;
773 for ( i = 0; i < max_cpu_nr; i++ )
774 if ( xc_set_cpufreq_para(xc_fd, i, UP_THRESHOLD, threshold) )
775 fprintf(stderr,
776 "[CPU%d] failed to set up scaling threshold\n", i);
777 }
778 else
779 {
780 if ( xc_set_cpufreq_para(xc_fd, cpuid, UP_THRESHOLD, threshold) )
781 fprintf(stderr, "failed to set up scaling threshold\n");
782 }
783 }
785 void scaling_governor_func(int argc, char *argv[])
786 {
787 int cpuid = -1;
788 char *name = NULL;
790 if ( argc >= 2 )
791 {
792 name = strdup(argv[1]);
793 if ( name == NULL )
794 goto out;
795 if ( sscanf(argv[0], "%d", &cpuid) != 1 )
796 {
797 free(name);
798 goto out;
799 }
800 }
801 else if ( argc > 0 )
802 {
803 name = strdup(argv[0]);
804 if ( name == NULL )
805 goto out;
806 }
807 else
808 goto out;
810 if ( cpuid < 0 )
811 {
812 int i;
813 for ( i = 0; i < max_cpu_nr; i++ )
814 if ( xc_set_cpufreq_gov(xc_fd, i, name) )
815 fprintf(stderr, "[CPU%d] failed to set governor name\n", i);
816 }
817 else
818 {
819 if ( xc_set_cpufreq_gov(xc_fd, cpuid, name) )
820 fprintf(stderr, "failed to set governor name\n");
821 }
823 free(name);
824 return ;
825 out:
826 fprintf(stderr, "failed to set governor name\n");
827 }
829 #define MAX_NR_CPU 512
831 void cpu_topology_func(int argc, char *argv[])
832 {
833 uint32_t cpu_to_core[MAX_NR_CPU];
834 uint32_t cpu_to_socket[MAX_NR_CPU];
835 struct xc_get_cputopo info;
836 int i, ret;
838 info.cpu_to_core = cpu_to_core;
839 info.cpu_to_socket = cpu_to_socket;
840 info.max_cpus = MAX_NR_CPU;
841 ret = xc_get_cputopo(xc_fd, &info);
842 if (!ret)
843 {
844 printf("CPU\tcore\tsocket\n");
845 for (i=0; i<info.nr_cpus; i++)
846 {
847 if ( info.cpu_to_core[i] != INVALID_TOPOLOGY_ID &&
848 info.cpu_to_socket[i] != INVALID_TOPOLOGY_ID )
849 {
850 printf("CPU%d\t %d\t %d\n", i, info.cpu_to_core[i],
851 info.cpu_to_socket[i]);
852 }
853 }
854 }
855 else
856 {
857 printf("Can not get Xen CPU topology!\n");
858 }
860 return ;
861 }
863 void set_sched_smt_func(int argc, char *argv[])
864 {
865 int value, rc;
867 if (argc != 1){
868 show_help();
869 exit(-1);
870 }
872 if ( !strncmp(argv[0], "disable", sizeof("disable")) )
873 {
874 value = 0;
875 }
876 else if ( !strncmp(argv[0], "enable", sizeof("enable")) )
877 {
878 value = 1;
879 }
880 else
881 {
882 show_help();
883 exit(-1);
884 }
886 rc = xc_set_sched_opt_smt(xc_fd, value);
887 printf("%s sched_smt_power_savings %s\n", argv[0],
888 rc? "failed":"succeeded" );
890 return;
891 }
893 void set_vcpu_migration_delay_func(int argc, char *argv[])
894 {
895 int value;
896 int rc;
898 if (argc != 1){
899 show_help();
900 exit(-1);
901 }
903 value = atoi(argv[0]);
905 if (value < 0)
906 {
907 printf("Please try non-negative vcpu migration delay\n");
908 exit(-1);
909 }
911 rc = xc_set_vcpu_migration_delay(xc_fd, value);
912 printf("%s to set vcpu migration delay to %d us\n",
913 rc? "Fail":"Succeed", value );
915 return;
916 }
918 void get_vcpu_migration_delay_func(int argc, char *argv[])
919 {
920 uint32_t value;
921 int rc;
923 if (argc != 0){
924 show_help();
925 exit(-1);
926 }
928 rc = xc_get_vcpu_migration_delay(xc_fd, &value);
929 if (!rc)
930 {
931 printf("Schduler vcpu migration delay is %d us\n", value);
932 }
933 else
934 {
935 printf("Failed to get scheduler vcpu migration delay, errno=%d\n", errno);
936 }
938 return;
939 }
941 void set_max_cstate_func(int argc, char *argv[])
942 {
943 int value, rc;
945 if ( argc != 1 || sscanf(argv[0], "%d", &value) != 1 || value < 0 )
946 {
947 show_help();
948 exit(-1);
949 }
951 rc = xc_set_cpuidle_max_cstate(xc_fd, (uint32_t)value);
952 printf("set max_cstate to C%d %s\n", value,
953 rc? "failed":"succeeded" );
955 return;
956 }
958 void enable_turbo_mode(int argc, char *argv[])
959 {
960 int cpuid = -1;
962 if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
963 cpuid = -1;
965 if ( cpuid >= max_cpu_nr )
966 cpuid = -1;
968 if ( cpuid < 0 )
969 {
970 /* enable turbo modes on all cpus,
971 * only make effects on dbs governor */
972 int i;
973 for ( i = 0; i < max_cpu_nr; i++ )
974 xc_enable_turbo(xc_fd, i);
975 }
976 else
977 xc_enable_turbo(xc_fd, cpuid);
978 }
980 void disable_turbo_mode(int argc, char *argv[])
981 {
982 int cpuid = -1;
984 if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
985 cpuid = -1;
987 if ( cpuid >= max_cpu_nr )
988 cpuid = -1;
990 if ( cpuid < 0 )
991 {
992 /* disable turbo modes on all cpus,
993 * only make effects on dbs governor */
994 int i;
995 for ( i = 0; i < max_cpu_nr; i++ )
996 xc_disable_turbo(xc_fd, i);
997 }
998 else
999 xc_disable_turbo(xc_fd, cpuid);
1002 struct {
1003 const char *name;
1004 void (*function)(int argc, char *argv[]);
1005 } main_options[] = {
1006 { "help", help_func },
1007 { "get-cpuidle-states", cxstat_func },
1008 { "get-cpufreq-states", pxstat_func },
1009 { "start", start_gather_func },
1010 { "get-cpufreq-para", cpufreq_para_func },
1011 { "set-scaling-maxfreq", scaling_max_freq_func },
1012 { "set-scaling-minfreq", scaling_min_freq_func },
1013 { "set-scaling-governor", scaling_governor_func },
1014 { "set-scaling-speed", scaling_speed_func },
1015 { "set-sampling-rate", scaling_sampling_rate_func },
1016 { "set-up-threshold", scaling_up_threshold_func },
1017 { "get-cpu-topology", cpu_topology_func},
1018 { "set-sched-smt", set_sched_smt_func},
1019 { "get-vcpu-migration-delay", get_vcpu_migration_delay_func},
1020 { "set-vcpu-migration-delay", set_vcpu_migration_delay_func},
1021 { "set-max-cstate", set_max_cstate_func},
1022 { "enable-turbo-mode", enable_turbo_mode },
1023 { "disable-turbo-mode", disable_turbo_mode },
1024 };
1026 int main(int argc, char *argv[])
1028 int i, ret = 0;
1029 xc_physinfo_t physinfo = { 0 };
1030 int nr_matches = 0;
1031 int matches_main_options[ARRAY_SIZE(main_options)];
1033 if ( argc < 2 )
1035 show_help();
1036 return 0;
1039 xc_fd = xc_interface_open();
1040 if ( xc_fd < 0 )
1042 fprintf(stderr, "failed to get the handler\n");
1043 return 0;
1046 ret = xc_physinfo(xc_fd, &physinfo);
1047 if ( ret )
1049 fprintf(stderr, "failed to get the processor information\n");
1050 xc_interface_close(xc_fd);
1051 return 0;
1053 max_cpu_nr = physinfo.nr_cpus;
1055 /* calculate how many options match with user's input */
1056 for ( i = 0; i < ARRAY_SIZE(main_options); i++ )
1057 if ( !strncmp(main_options[i].name, argv[1], strlen(argv[1])) )
1058 matches_main_options[nr_matches++] = i;
1060 if ( nr_matches > 1 )
1062 fprintf(stderr, "Ambigious options: ");
1063 for ( i = 0; i < nr_matches; i++ )
1064 fprintf(stderr, " %s", main_options[matches_main_options[i]].name);
1065 fprintf(stderr, "\n");
1067 else if ( nr_matches == 1 )
1068 /* dispatch to the corresponding function handler */
1069 main_options[matches_main_options[0]].function(argc - 2, argv + 2);
1070 else
1071 show_help();
1073 xc_interface_close(xc_fd);
1074 return 0;