ia64/xen-unstable

view tools/misc/xenpm.c @ 19648:f0e2df69a8eb

x86 hvm: Allow cross-vendor migration

Intercept #UD and emulate SYSCALL/SYSENTER/SYSEXIT as necessary.

Signed-off-by: Christoph Egger <Christoph.Egger@amd.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue May 26 15:01:36 2009 +0100 (2009-05-26)
parents 5966b71195b4
children
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 );
66 }
67 /* wrapper function */
68 void help_func(int argc, char *argv[])
69 {
70 show_help();
71 }
73 static void print_cxstat(int cpuid, struct xc_cx_stat *cxstat)
74 {
75 int i;
77 printf("cpu id : %d\n", cpuid);
78 printf("total C-states : %d\n", cxstat->nr);
79 printf("idle time(ms) : %"PRIu64"\n",
80 cxstat->idle_time/1000000UL);
81 for ( i = 0; i < cxstat->nr; i++ )
82 {
83 printf("C%d : transition [%020"PRIu64"]\n",
84 i, cxstat->triggers[i]);
85 printf(" residency [%020"PRIu64" ms]\n",
86 cxstat->residencies[i]/1000000UL);
87 }
88 printf("\n");
89 }
91 /* show cpu idle information on CPU cpuid */
92 static int get_cxstat_by_cpuid(int xc_fd, int cpuid, struct xc_cx_stat *cxstat)
93 {
94 int ret = 0;
95 int max_cx_num = 0;
97 ret = xc_pm_get_max_cx(xc_fd, cpuid, &max_cx_num);
98 if ( ret )
99 return errno;
101 if ( !cxstat )
102 return -EINVAL;
104 cxstat->triggers = malloc(max_cx_num * sizeof(uint64_t));
105 if ( !cxstat->triggers )
106 return -ENOMEM;
107 cxstat->residencies = malloc(max_cx_num * sizeof(uint64_t));
108 if ( !cxstat->residencies )
109 {
110 free(cxstat->triggers);
111 return -ENOMEM;
112 }
114 ret = xc_pm_get_cxstat(xc_fd, cpuid, cxstat);
115 if( ret )
116 {
117 int temp = errno;
118 free(cxstat->triggers);
119 free(cxstat->residencies);
120 cxstat->triggers = NULL;
121 cxstat->residencies = NULL;
122 return temp;
123 }
125 return 0;
126 }
128 static int show_max_cstate(int xc_fd)
129 {
130 int ret = 0;
131 uint32_t value;
133 if ( (ret = xc_get_cpuidle_max_cstate(xc_fd, &value)) )
134 return ret;
136 printf("Max C-state: C%d\n\n", value);
137 return 0;
138 }
140 static int show_cxstat_by_cpuid(int xc_fd, int cpuid)
141 {
142 int ret = 0;
143 struct xc_cx_stat cxstatinfo;
145 ret = get_cxstat_by_cpuid(xc_fd, cpuid, &cxstatinfo);
146 if ( ret )
147 return ret;
149 print_cxstat(cpuid, &cxstatinfo);
151 free(cxstatinfo.triggers);
152 free(cxstatinfo.residencies);
153 return 0;
154 }
156 void cxstat_func(int argc, char *argv[])
157 {
158 int cpuid = -1;
160 if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
161 cpuid = -1;
163 if ( cpuid >= max_cpu_nr )
164 cpuid = -1;
166 show_max_cstate(xc_fd);
168 if ( cpuid < 0 )
169 {
170 /* show cxstates on all cpus */
171 int i;
172 for ( i = 0; i < max_cpu_nr; i++ )
173 if ( show_cxstat_by_cpuid(xc_fd, i) == -ENODEV )
174 break;
175 }
176 else
177 show_cxstat_by_cpuid(xc_fd, cpuid);
178 }
180 static void print_pxstat(int cpuid, struct xc_px_stat *pxstat)
181 {
182 int i;
184 printf("cpu id : %d\n", cpuid);
185 printf("total P-states : %d\n", pxstat->total);
186 printf("usable P-states : %d\n", pxstat->usable);
187 printf("current frequency : %"PRIu64" MHz\n",
188 pxstat->pt[pxstat->cur].freq);
189 for ( i = 0; i < pxstat->total; i++ )
190 {
191 if ( pxstat->cur == i )
192 printf("*P%d", i);
193 else
194 printf("P%d ", i);
195 printf(" : freq [%04"PRIu64" MHz]\n",
196 pxstat->pt[i].freq);
197 printf(" transition [%020"PRIu64"]\n",
198 pxstat->pt[i].count);
199 printf(" residency [%020"PRIu64" ms]\n",
200 pxstat->pt[i].residency/1000000UL);
201 }
202 printf("\n");
203 }
205 /* show cpu frequency information on CPU cpuid */
206 static int get_pxstat_by_cpuid(int xc_fd, int cpuid, struct xc_px_stat *pxstat)
207 {
208 int ret = 0;
209 int max_px_num = 0;
211 ret = xc_pm_get_max_px(xc_fd, cpuid, &max_px_num);
212 if ( ret )
213 return errno;
215 if ( !pxstat)
216 return -EINVAL;
218 pxstat->trans_pt = malloc(max_px_num * max_px_num *
219 sizeof(uint64_t));
220 if ( !pxstat->trans_pt )
221 return -ENOMEM;
222 pxstat->pt = malloc(max_px_num * sizeof(struct xc_px_val));
223 if ( !pxstat->pt )
224 {
225 free(pxstat->trans_pt);
226 return -ENOMEM;
227 }
229 ret = xc_pm_get_pxstat(xc_fd, cpuid, pxstat);
230 if( ret )
231 {
232 int temp = errno;
233 free(pxstat->trans_pt);
234 free(pxstat->pt);
235 pxstat->trans_pt = NULL;
236 pxstat->pt = NULL;
237 return temp;
238 }
240 return 0;
241 }
243 /* show cpu actual average freq information on CPU cpuid */
244 static int get_avgfreq_by_cpuid(int xc_fd, int cpuid, int *avgfreq)
245 {
246 int ret = 0;
248 ret = xc_get_cpufreq_avgfreq(xc_fd, cpuid, avgfreq);
249 if ( ret )
250 {
251 return errno;
252 }
254 return 0;
255 }
257 static int show_pxstat_by_cpuid(int xc_fd, int cpuid)
258 {
259 int ret = 0;
260 struct xc_px_stat pxstatinfo;
262 ret = get_pxstat_by_cpuid(xc_fd, cpuid, &pxstatinfo);
263 if ( ret )
264 return ret;
266 print_pxstat(cpuid, &pxstatinfo);
268 free(pxstatinfo.trans_pt);
269 free(pxstatinfo.pt);
270 return 0;
271 }
273 void pxstat_func(int argc, char *argv[])
274 {
275 int cpuid = -1;
277 if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
278 cpuid = -1;
280 if ( cpuid >= max_cpu_nr )
281 cpuid = -1;
283 if ( cpuid < 0 )
284 {
285 /* show pxstates on all cpus */
286 int i;
287 for ( i = 0; i < max_cpu_nr; i++ )
288 if ( show_pxstat_by_cpuid(xc_fd, i) == -ENODEV )
289 break;
290 }
291 else
292 show_pxstat_by_cpuid(xc_fd, cpuid);
293 }
295 static uint64_t usec_start, usec_end;
296 static struct xc_cx_stat *cxstat, *cxstat_start, *cxstat_end;
297 static struct xc_px_stat *pxstat, *pxstat_start, *pxstat_end;
298 static int *avgfreq;
299 static uint64_t *sum, *sum_cx, *sum_px;
301 static void signal_int_handler(int signo)
302 {
303 int i, j;
304 struct timeval tv;
305 int cx_cap = 0, px_cap = 0;
307 if ( gettimeofday(&tv, NULL) == -1 )
308 {
309 fprintf(stderr, "failed to get timeofday\n");
310 return ;
311 }
312 usec_end = tv.tv_sec * 1000000UL + tv.tv_usec;
314 if ( get_cxstat_by_cpuid(xc_fd, 0, NULL) != -ENODEV )
315 {
316 cx_cap = 1;
317 for ( i = 0; i < max_cpu_nr; i++ )
318 if ( !get_cxstat_by_cpuid(xc_fd, i, &cxstat_end[i]) )
319 for ( j = 0; j < cxstat_end[i].nr; j++ )
320 sum_cx[i] += cxstat_end[i].residencies[j] -
321 cxstat_start[i].residencies[j];
322 }
324 if ( get_pxstat_by_cpuid(xc_fd, 0, NULL) != -ENODEV )
325 {
326 px_cap = 1;
327 for ( i = 0; i < max_cpu_nr; i++ )
328 if ( !get_pxstat_by_cpuid(xc_fd, i , &pxstat_end[i]) )
329 for ( j = 0; j < pxstat_end[i].total; j++ )
330 sum_px[i] += pxstat_end[i].pt[j].residency -
331 pxstat_start[i].pt[j].residency;
332 }
334 for ( i = 0; i < max_cpu_nr; i++ )
335 get_avgfreq_by_cpuid(xc_fd, i, &avgfreq[i]);
337 printf("Elapsed time (ms): %"PRIu64"\n", (usec_end - usec_start) / 1000UL);
338 for ( i = 0; i < max_cpu_nr; i++ )
339 {
340 uint64_t res, triggers;
341 double avg_res;
343 printf("\nCPU%d:\tResidency(ms)\t\tAvg Res(ms)\n",i);
344 if ( cx_cap && sum_cx[i] > 0 )
345 {
346 for ( j = 0; j < cxstat_end[i].nr; j++ )
347 {
348 res = cxstat_end[i].residencies[j] -
349 cxstat_start[i].residencies[j];
350 triggers = cxstat_end[i].triggers[j] -
351 cxstat_start[i].triggers[j];
352 avg_res = (triggers==0) ? 0: (double)res/triggers/1000000.0;
353 printf(" C%d\t%"PRIu64"\t(%5.2f%%)\t%.2f\n", j, res/1000000UL,
354 100 * res / (double)sum_cx[i], avg_res );
355 }
356 printf("\n");
357 }
358 if ( px_cap && sum_px[i]>0 )
359 {
360 for ( j = 0; j < pxstat_end[i].total; j++ )
361 {
362 res = pxstat_end[i].pt[j].residency -
363 pxstat_start[i].pt[j].residency;
364 printf(" P%d\t%"PRIu64"\t(%5.2f%%)\n", j,
365 res / 1000000UL, 100UL * res / (double)sum_px[i]);
366 }
367 }
368 printf(" Avg freq\t%d\tKHz\n", avgfreq[i]);
369 }
371 /* some clean up and then exits */
372 for ( i = 0; i < 2 * max_cpu_nr; i++ )
373 {
374 free(cxstat[i].triggers);
375 free(cxstat[i].residencies);
376 free(pxstat[i].trans_pt);
377 free(pxstat[i].pt);
378 }
379 free(cxstat);
380 free(pxstat);
381 free(sum);
382 free(avgfreq);
383 xc_interface_close(xc_fd);
384 exit(0);
385 }
387 void start_gather_func(int argc, char *argv[])
388 {
389 int i;
390 struct timeval tv;
391 int timeout = 0;
393 if ( argc == 1 )
394 {
395 sscanf(argv[0], "%d", &timeout);
396 if ( timeout <= 0 )
397 fprintf(stderr, "failed to set timeout seconds, falling back...\n");
398 else
399 printf("Timeout set to %d seconds\n", timeout);
400 }
402 if ( gettimeofday(&tv, NULL) == -1 )
403 {
404 fprintf(stderr, "failed to get timeofday\n");
405 return ;
406 }
407 usec_start = tv.tv_sec * 1000000UL + tv.tv_usec;
409 sum = malloc(sizeof(uint64_t) * 2 * max_cpu_nr);
410 if ( sum == NULL )
411 return ;
412 cxstat = malloc(sizeof(struct xc_cx_stat) * 2 * max_cpu_nr);
413 if ( cxstat == NULL )
414 {
415 free(sum);
416 return ;
417 }
418 pxstat = malloc(sizeof(struct xc_px_stat) * 2 * max_cpu_nr);
419 if ( pxstat == NULL )
420 {
421 free(sum);
422 free(cxstat);
423 return ;
424 }
425 avgfreq = malloc(sizeof(int) * max_cpu_nr);
426 if ( avgfreq == NULL )
427 {
428 free(sum);
429 free(cxstat);
430 free(pxstat);
431 return ;
432 }
433 memset(sum, 0, sizeof(uint64_t) * 2 * max_cpu_nr);
434 memset(cxstat, 0, sizeof(struct xc_cx_stat) * 2 * max_cpu_nr);
435 memset(pxstat, 0, sizeof(struct xc_px_stat) * 2 * max_cpu_nr);
436 memset(avgfreq, 0, sizeof(int) * max_cpu_nr);
437 sum_cx = sum;
438 sum_px = sum + max_cpu_nr;
439 cxstat_start = cxstat;
440 cxstat_end = cxstat + max_cpu_nr;
441 pxstat_start = pxstat;
442 pxstat_end = pxstat + max_cpu_nr;
444 if ( get_cxstat_by_cpuid(xc_fd, 0, NULL) == -ENODEV &&
445 get_pxstat_by_cpuid(xc_fd, 0, NULL) == -ENODEV )
446 {
447 fprintf(stderr, "Xen cpu idle and frequency is disabled!\n");
448 return ;
449 }
451 for ( i = 0; i < max_cpu_nr; i++ )
452 {
453 get_cxstat_by_cpuid(xc_fd, i, &cxstat_start[i]);
454 get_pxstat_by_cpuid(xc_fd, i, &pxstat_start[i]);
455 get_avgfreq_by_cpuid(xc_fd, i, &avgfreq[i]);
456 }
458 if (signal(SIGINT, signal_int_handler) == SIG_ERR)
459 {
460 fprintf(stderr, "failed to set signal int handler\n");
461 free(sum);
462 free(pxstat);
463 free(cxstat);
464 free(avgfreq);
465 return ;
466 }
468 if ( timeout > 0 )
469 {
470 if ( signal(SIGALRM, signal_int_handler) == SIG_ERR )
471 {
472 fprintf(stderr, "failed to set signal alarm handler\n");
473 free(sum);
474 free(pxstat);
475 free(cxstat);
476 free(avgfreq);
477 return ;
478 }
479 alarm(timeout);
480 }
482 printf("Start sampling, waiting for CTRL-C or SIGINT or SIGALARM signal ...\n");
484 pause();
485 }
487 /* print out parameters about cpu frequency */
488 static void print_cpufreq_para(int cpuid, struct xc_get_cpufreq_para *p_cpufreq)
489 {
490 int i;
492 printf("cpu id : %d\n", cpuid);
494 printf("affected_cpus :");
495 for ( i = 0; i < p_cpufreq->cpu_num; i++ )
496 if ( i == cpuid )
497 printf(" *%d", p_cpufreq->affected_cpus[i]);
498 else
499 printf(" %d", p_cpufreq->affected_cpus[i]);
500 printf("\n");
502 printf("cpuinfo frequency : max [%u] min [%u] cur [%u]\n",
503 p_cpufreq->cpuinfo_max_freq,
504 p_cpufreq->cpuinfo_min_freq,
505 p_cpufreq->cpuinfo_cur_freq);
507 printf("scaling_driver : %s\n", p_cpufreq->scaling_driver);
509 printf("scaling_avail_gov : %s\n",
510 p_cpufreq->scaling_available_governors);
512 printf("current_governor : %s\n", p_cpufreq->scaling_governor);
513 if ( !strncmp(p_cpufreq->scaling_governor,
514 "userspace", CPUFREQ_NAME_LEN) )
515 {
516 printf(" userspace specific :\n");
517 printf(" scaling_setspeed : %u\n",
518 p_cpufreq->u.userspace.scaling_setspeed);
519 }
520 else if ( !strncmp(p_cpufreq->scaling_governor,
521 "ondemand", CPUFREQ_NAME_LEN) )
522 {
523 printf(" ondemand specific :\n");
524 printf(" sampling_rate : max [%u] min [%u] cur [%u]\n",
525 p_cpufreq->u.ondemand.sampling_rate_max,
526 p_cpufreq->u.ondemand.sampling_rate_min,
527 p_cpufreq->u.ondemand.sampling_rate);
528 printf(" up_threshold : %u\n",
529 p_cpufreq->u.ondemand.up_threshold);
530 }
532 printf("scaling_avail_freq :");
533 for ( i = 0; i < p_cpufreq->freq_num; i++ )
534 if ( p_cpufreq->scaling_available_frequencies[i] ==
535 p_cpufreq->scaling_cur_freq )
536 printf(" *%d", p_cpufreq->scaling_available_frequencies[i]);
537 else
538 printf(" %d", p_cpufreq->scaling_available_frequencies[i]);
539 printf("\n");
541 printf("scaling frequency : max [%u] min [%u] cur [%u]\n",
542 p_cpufreq->scaling_max_freq,
543 p_cpufreq->scaling_min_freq,
544 p_cpufreq->scaling_cur_freq);
545 printf("\n");
546 }
548 /* show cpu frequency parameters information on CPU cpuid */
549 static int show_cpufreq_para_by_cpuid(int xc_fd, int cpuid)
550 {
551 int ret = 0;
552 struct xc_get_cpufreq_para cpufreq_para, *p_cpufreq = &cpufreq_para;
554 p_cpufreq->cpu_num = 0;
555 p_cpufreq->freq_num = 0;
556 p_cpufreq->gov_num = 0;
557 p_cpufreq->affected_cpus = NULL;
558 p_cpufreq->scaling_available_frequencies = NULL;
559 p_cpufreq->scaling_available_governors = NULL;
561 do
562 {
563 free(p_cpufreq->affected_cpus);
564 free(p_cpufreq->scaling_available_frequencies);
565 free(p_cpufreq->scaling_available_governors);
567 p_cpufreq->affected_cpus = NULL;
568 p_cpufreq->scaling_available_frequencies = NULL;
569 p_cpufreq->scaling_available_governors = NULL;
571 if (!(p_cpufreq->affected_cpus =
572 malloc(p_cpufreq->cpu_num * sizeof(uint32_t))))
573 {
574 fprintf(stderr,
575 "[CPU%d] failed to malloc for affected_cpus\n",
576 cpuid);
577 ret = -ENOMEM;
578 goto out;
579 }
580 if (!(p_cpufreq->scaling_available_frequencies =
581 malloc(p_cpufreq->freq_num * sizeof(uint32_t))))
582 {
583 fprintf(stderr,
584 "[CPU%d] failed to malloc for scaling_available_frequencies\n",
585 cpuid);
586 ret = -ENOMEM;
587 goto out;
588 }
589 if (!(p_cpufreq->scaling_available_governors =
590 malloc(p_cpufreq->gov_num * CPUFREQ_NAME_LEN * sizeof(char))))
591 {
592 fprintf(stderr,
593 "[CPU%d] failed to malloc for scaling_available_governors\n",
594 cpuid);
595 ret = -ENOMEM;
596 goto out;
597 }
599 ret = xc_get_cpufreq_para(xc_fd, cpuid, p_cpufreq);
600 } while ( ret && errno == EAGAIN );
602 if ( ret == 0 )
603 print_cpufreq_para(cpuid, p_cpufreq);
604 else if ( errno == ENODEV )
605 {
606 ret = -ENODEV;
607 fprintf(stderr, "Xen cpufreq is not enabled!\n");
608 }
609 else
610 fprintf(stderr,
611 "[CPU%d] failed to get cpufreq parameter\n",
612 cpuid);
614 out:
615 free(p_cpufreq->scaling_available_governors);
616 free(p_cpufreq->scaling_available_frequencies);
617 free(p_cpufreq->affected_cpus);
619 return ret;
620 }
622 void cpufreq_para_func(int argc, char *argv[])
623 {
624 int cpuid = -1;
626 if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
627 cpuid = -1;
629 if ( cpuid >= max_cpu_nr )
630 cpuid = -1;
632 if ( cpuid < 0 )
633 {
634 /* show cpu freqency information on all cpus */
635 int i;
636 for ( i = 0; i < max_cpu_nr; i++ )
637 if ( show_cpufreq_para_by_cpuid(xc_fd, i) == -ENODEV )
638 break;
639 }
640 else
641 show_cpufreq_para_by_cpuid(xc_fd, cpuid);
642 }
644 void scaling_max_freq_func(int argc, char *argv[])
645 {
646 int cpuid = -1, freq = -1;
648 if ( (argc >= 2 && (sscanf(argv[1], "%d", &freq) != 1 ||
649 sscanf(argv[0], "%d", &cpuid) != 1)) ||
650 (argc == 1 && sscanf(argv[0], "%d", &freq) != 1 ) ||
651 argc == 0 )
652 {
653 fprintf(stderr, "failed to set scaling max freq\n");
654 return ;
655 }
657 if ( cpuid < 0 )
658 {
659 int i;
660 for ( i = 0; i < max_cpu_nr; i++ )
661 if ( xc_set_cpufreq_para(xc_fd, i, SCALING_MAX_FREQ, freq) )
662 fprintf(stderr, "[CPU%d] failed to set scaling max freq\n", i);
663 }
664 else
665 {
666 if ( xc_set_cpufreq_para(xc_fd, cpuid, SCALING_MAX_FREQ, freq) )
667 fprintf(stderr, "failed to set scaling max freq\n");
668 }
669 }
671 void scaling_min_freq_func(int argc, char *argv[])
672 {
673 int cpuid = -1, freq = -1;
675 if ( (argc >= 2 && (sscanf(argv[1], "%d", &freq) != 1 ||
676 sscanf(argv[0], "%d", &cpuid) != 1) ) ||
677 (argc == 1 && sscanf(argv[0], "%d", &freq) != 1 ) ||
678 argc == 0 )
679 {
680 fprintf(stderr, "failed to set scaling min freq\n");
681 return ;
682 }
684 if ( cpuid < 0 )
685 {
686 int i;
687 for ( i = 0; i < max_cpu_nr; i++ )
688 if ( xc_set_cpufreq_para(xc_fd, i, SCALING_MIN_FREQ, freq) )
689 fprintf(stderr, "[CPU%d] failed to set scaling min freq\n", i);
690 }
691 else
692 {
693 if ( xc_set_cpufreq_para(xc_fd, cpuid, SCALING_MIN_FREQ, freq) )
694 fprintf(stderr, "failed to set scaling min freq\n");
695 }
696 }
698 void scaling_speed_func(int argc, char *argv[])
699 {
700 int cpuid = -1, speed = -1;
702 if ( (argc >= 2 && (sscanf(argv[1], "%d", &speed) != 1 ||
703 sscanf(argv[0], "%d", &cpuid) != 1) ) ||
704 (argc == 1 && sscanf(argv[0], "%d", &speed) != 1 ) ||
705 argc == 0 )
706 {
707 fprintf(stderr, "failed to set scaling speed\n");
708 return ;
709 }
711 if ( cpuid < 0 )
712 {
713 int i;
714 for ( i = 0; i < max_cpu_nr; i++ )
715 if ( xc_set_cpufreq_para(xc_fd, i, SCALING_SETSPEED, speed) )
716 fprintf(stderr, "[CPU%d] failed to set scaling speed\n", i);
717 }
718 else
719 {
720 if ( xc_set_cpufreq_para(xc_fd, cpuid, SCALING_SETSPEED, speed) )
721 fprintf(stderr, "failed to set scaling speed\n");
722 }
723 }
725 void scaling_sampling_rate_func(int argc, char *argv[])
726 {
727 int cpuid = -1, rate = -1;
729 if ( (argc >= 2 && (sscanf(argv[1], "%d", &rate) != 1 ||
730 sscanf(argv[0], "%d", &cpuid) != 1) ) ||
731 (argc == 1 && sscanf(argv[0], "%d", &rate) != 1 ) ||
732 argc == 0 )
733 {
734 fprintf(stderr, "failed to set scaling sampling rate\n");
735 return ;
736 }
738 if ( cpuid < 0 )
739 {
740 int i;
741 for ( i = 0; i < max_cpu_nr; i++ )
742 if ( xc_set_cpufreq_para(xc_fd, i, SAMPLING_RATE, rate) )
743 fprintf(stderr,
744 "[CPU%d] failed to set scaling sampling rate\n", i);
745 }
746 else
747 {
748 if ( xc_set_cpufreq_para(xc_fd, cpuid, SAMPLING_RATE, rate) )
749 fprintf(stderr, "failed to set scaling sampling rate\n");
750 }
751 }
753 void scaling_up_threshold_func(int argc, char *argv[])
754 {
755 int cpuid = -1, threshold = -1;
757 if ( (argc >= 2 && (sscanf(argv[1], "%d", &threshold) != 1 ||
758 sscanf(argv[0], "%d", &cpuid) != 1) ) ||
759 (argc == 1 && sscanf(argv[0], "%d", &threshold) != 1 ) ||
760 argc == 0 )
761 {
762 fprintf(stderr, "failed to set up scaling threshold\n");
763 return ;
764 }
766 if ( cpuid < 0 )
767 {
768 int i;
769 for ( i = 0; i < max_cpu_nr; i++ )
770 if ( xc_set_cpufreq_para(xc_fd, i, UP_THRESHOLD, threshold) )
771 fprintf(stderr,
772 "[CPU%d] failed to set up scaling threshold\n", i);
773 }
774 else
775 {
776 if ( xc_set_cpufreq_para(xc_fd, cpuid, UP_THRESHOLD, threshold) )
777 fprintf(stderr, "failed to set up scaling threshold\n");
778 }
779 }
781 void scaling_governor_func(int argc, char *argv[])
782 {
783 int cpuid = -1;
784 char *name = NULL;
786 if ( argc >= 2 )
787 {
788 name = strdup(argv[1]);
789 if ( name == NULL )
790 goto out;
791 if ( sscanf(argv[0], "%d", &cpuid) != 1 )
792 {
793 free(name);
794 goto out;
795 }
796 }
797 else if ( argc > 0 )
798 {
799 name = strdup(argv[0]);
800 if ( name == NULL )
801 goto out;
802 }
803 else
804 goto out;
806 if ( cpuid < 0 )
807 {
808 int i;
809 for ( i = 0; i < max_cpu_nr; i++ )
810 if ( xc_set_cpufreq_gov(xc_fd, i, name) )
811 fprintf(stderr, "[CPU%d] failed to set governor name\n", i);
812 }
813 else
814 {
815 if ( xc_set_cpufreq_gov(xc_fd, cpuid, name) )
816 fprintf(stderr, "failed to set governor name\n");
817 }
819 free(name);
820 return ;
821 out:
822 fprintf(stderr, "failed to set governor name\n");
823 }
825 #define MAX_NR_CPU 512
827 void cpu_topology_func(int argc, char *argv[])
828 {
829 uint32_t cpu_to_core[MAX_NR_CPU];
830 uint32_t cpu_to_socket[MAX_NR_CPU];
831 struct xc_get_cputopo info;
832 int i, ret;
834 info.cpu_to_core = cpu_to_core;
835 info.cpu_to_socket = cpu_to_socket;
836 info.max_cpus = MAX_NR_CPU;
837 ret = xc_get_cputopo(xc_fd, &info);
838 if (!ret)
839 {
840 printf("CPU\tcore\tsocket\n");
841 for (i=0; i<info.nr_cpus; i++)
842 {
843 if ( info.cpu_to_core[i] != INVALID_TOPOLOGY_ID &&
844 info.cpu_to_socket[i] != INVALID_TOPOLOGY_ID )
845 {
846 printf("CPU%d\t %d\t %d\n", i, info.cpu_to_core[i],
847 info.cpu_to_socket[i]);
848 }
849 }
850 }
851 else
852 {
853 printf("Can not get Xen CPU topology!\n");
854 }
856 return ;
857 }
859 void set_sched_smt_func(int argc, char *argv[])
860 {
861 int value, rc;
863 if (argc != 1){
864 show_help();
865 exit(-1);
866 }
868 if ( !strncmp(argv[0], "disable", sizeof("disable")) )
869 {
870 value = 0;
871 }
872 else if ( !strncmp(argv[0], "enable", sizeof("enable")) )
873 {
874 value = 1;
875 }
876 else
877 {
878 show_help();
879 exit(-1);
880 }
882 rc = xc_set_sched_opt_smt(xc_fd, value);
883 printf("%s sched_smt_power_savings %s\n", argv[0],
884 rc? "failed":"succeeded" );
886 return;
887 }
889 void set_vcpu_migration_delay_func(int argc, char *argv[])
890 {
891 int value;
892 int rc;
894 if (argc != 1){
895 show_help();
896 exit(-1);
897 }
899 value = atoi(argv[0]);
901 if (value < 0)
902 {
903 printf("Please try non-negative vcpu migration delay\n");
904 exit(-1);
905 }
907 rc = xc_set_vcpu_migration_delay(xc_fd, value);
908 printf("%s to set vcpu migration delay to %d us\n",
909 rc? "Fail":"Succeed", value );
911 return;
912 }
914 void get_vcpu_migration_delay_func(int argc, char *argv[])
915 {
916 uint32_t value;
917 int rc;
919 if (argc != 0){
920 show_help();
921 exit(-1);
922 }
924 rc = xc_get_vcpu_migration_delay(xc_fd, &value);
925 if (!rc)
926 {
927 printf("Schduler vcpu migration delay is %d us\n", value);
928 }
929 else
930 {
931 printf("Failed to get scheduler vcpu migration delay, errno=%d\n", errno);
932 }
934 return;
935 }
937 void set_max_cstate_func(int argc, char *argv[])
938 {
939 int value, rc;
941 if ( argc != 1 || sscanf(argv[0], "%d", &value) != 1 || value < 0 )
942 {
943 show_help();
944 exit(-1);
945 }
947 rc = xc_set_cpuidle_max_cstate(xc_fd, (uint32_t)value);
948 printf("set max_cstate to C%d %s\n", value,
949 rc? "failed":"succeeded" );
951 return;
952 }
954 struct {
955 const char *name;
956 void (*function)(int argc, char *argv[]);
957 } main_options[] = {
958 { "help", help_func },
959 { "get-cpuidle-states", cxstat_func },
960 { "get-cpufreq-states", pxstat_func },
961 { "start", start_gather_func },
962 { "get-cpufreq-para", cpufreq_para_func },
963 { "set-scaling-maxfreq", scaling_max_freq_func },
964 { "set-scaling-minfreq", scaling_min_freq_func },
965 { "set-scaling-governor", scaling_governor_func },
966 { "set-scaling-speed", scaling_speed_func },
967 { "set-sampling-rate", scaling_sampling_rate_func },
968 { "set-up-threshold", scaling_up_threshold_func },
969 { "get-cpu-topology", cpu_topology_func},
970 { "set-sched-smt", set_sched_smt_func},
971 { "get-vcpu-migration-delay", get_vcpu_migration_delay_func},
972 { "set-vcpu-migration-delay", set_vcpu_migration_delay_func},
973 { "set-max-cstate", set_max_cstate_func},
974 };
976 int main(int argc, char *argv[])
977 {
978 int i, ret = 0;
979 xc_physinfo_t physinfo = { 0 };
980 int nr_matches = 0;
981 int matches_main_options[ARRAY_SIZE(main_options)];
983 if ( argc < 2 )
984 {
985 show_help();
986 return 0;
987 }
989 xc_fd = xc_interface_open();
990 if ( xc_fd < 0 )
991 {
992 fprintf(stderr, "failed to get the handler\n");
993 return 0;
994 }
996 ret = xc_physinfo(xc_fd, &physinfo);
997 if ( ret )
998 {
999 fprintf(stderr, "failed to get the processor information\n");
1000 xc_interface_close(xc_fd);
1001 return 0;
1003 max_cpu_nr = physinfo.nr_cpus;
1005 /* calculate how many options match with user's input */
1006 for ( i = 0; i < ARRAY_SIZE(main_options); i++ )
1007 if ( !strncmp(main_options[i].name, argv[1], strlen(argv[1])) )
1008 matches_main_options[nr_matches++] = i;
1010 if ( nr_matches > 1 )
1012 fprintf(stderr, "Ambigious options: ");
1013 for ( i = 0; i < nr_matches; i++ )
1014 fprintf(stderr, " %s", main_options[matches_main_options[i]].name);
1015 fprintf(stderr, "\n");
1017 else if ( nr_matches == 1 )
1018 /* dispatch to the corresponding function handler */
1019 main_options[matches_main_options[0]].function(argc - 2, argv + 2);
1020 else
1021 show_help();
1023 xc_interface_close(xc_fd);
1024 return 0;