debuggers.hg

view tools/misc/xenpm.c @ 22358:9fad5e5e2fc1

libxc: finalise transition to hypercall buffers.

Rename xc_set_xen_guest_handle to set_xen_guest_handle[0] and remove now
unused functions:
- xc_memalign
- lock_pages
- unlock_pages
- hcall_buf_prep
- hcall_buf_release

[0] sed -i -e 's/xc_set_xen_guest_handle/set_xen_guest_handle/g' \
tools/libxc/*.[ch] \
tools/python/xen/lowlevel/xc/xc.c \
tools/python/xen/lowlevel/acm/acm.c \
tools/libxc/ia64/xc_ia64_stubs.c \
tools/security/secpol_tool.c \
tools/misc/xenpm.c

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Signed-off-by: Ian Jackson <ian.jackson.citrix.com>
author Ian Campbell <ian.campbell@citrix.com>
date Fri Oct 22 15:14:51 2010 +0100 (2010-10-22)
parents c3dce5f3f026
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 */
18 #define MAX_NR_CPU 512
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <getopt.h>
25 #include <errno.h>
26 #include <signal.h>
28 #include <xenctrl.h>
29 #include <inttypes.h>
30 #include <sys/time.h>
32 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
34 #define CPUFREQ_TURBO_DISABLED -1
35 #define CPUFREQ_TURBO_UNSUPPORTED 0
36 #define CPUFREQ_TURBO_ENABLED 1
38 static xc_interface *xc_handle;
39 static int max_cpu_nr;
41 /* help message */
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-para [cpuid] list cpu freq parameter of CPU <cpuid> or all\n"
51 " set-scaling-maxfreq [cpuid] <HZ> set max cpu frequency <HZ> on CPU <cpuid>\n"
52 " or all CPUs\n"
53 " set-scaling-minfreq [cpuid] <HZ> set min cpu frequency <HZ> on CPU <cpuid>\n"
54 " or all CPUs\n"
55 " set-scaling-speed [cpuid] <num> set scaling speed on CPU <cpuid> or all\n"
56 " it is used in userspace governor.\n"
57 " set-scaling-governor [cpuid] <gov> set scaling governor on CPU <cpuid> or all\n"
58 " as userspace/performance/powersave/ondemand\n"
59 " set-sampling-rate [cpuid] <num> set sampling rate on CPU <cpuid> or all\n"
60 " it is used in ondemand governor.\n"
61 " set-up-threshold [cpuid] <num> set up threshold on CPU <cpuid> or all\n"
62 " it is used in ondemand governor.\n"
63 " get-cpu-topology get thread/core/socket topology info\n"
64 " set-sched-smt enable|disable enable/disable scheduler smt power saving\n"
65 " set-vcpu-migration-delay <num> set scheduler vcpu migration delay in us\n"
66 " get-vcpu-migration-delay get scheduler vcpu migration delay\n"
67 " set-max-cstate <num> set the C-State limitation (<num> >= 0)\n"
68 " start [seconds] start collect Cx/Px statistics,\n"
69 " output after CTRL-C or SIGINT or several seconds.\n"
70 " enable-turbo-mode [cpuid] enable Turbo Mode for processors that support it.\n"
71 " disable-turbo-mode [cpuid] disable Turbo Mode for processors that support it.\n"
72 );
73 }
74 /* wrapper function */
75 void help_func(int argc, char *argv[])
76 {
77 show_help();
78 }
80 static void print_cxstat(int cpuid, struct xc_cx_stat *cxstat)
81 {
82 int i;
84 printf("cpu id : %d\n", cpuid);
85 printf("total C-states : %d\n", cxstat->nr);
86 printf("idle time(ms) : %"PRIu64"\n",
87 cxstat->idle_time/1000000UL);
88 for ( i = 0; i < cxstat->nr; i++ )
89 {
90 printf("C%d : transition [%020"PRIu64"]\n",
91 i, cxstat->triggers[i]);
92 printf(" residency [%020"PRIu64" ms]\n",
93 cxstat->residencies[i]/1000000UL);
94 }
95 printf("pc3 : [%020"PRIu64" ms]\n"
96 "pc6 : [%020"PRIu64" ms]\n"
97 "pc7 : [%020"PRIu64" ms]\n",
98 cxstat->pc3/1000000UL, cxstat->pc6/1000000UL, cxstat->pc7/1000000UL);
99 printf("cc3 : [%020"PRIu64" ms]\n"
100 "cc6 : [%020"PRIu64" ms]\n",
101 cxstat->cc3/1000000UL, cxstat->cc6/1000000UL);
102 printf("\n");
103 }
105 /* show cpu idle information on CPU cpuid */
106 static int get_cxstat_by_cpuid(xc_interface *xc_handle, int cpuid, struct xc_cx_stat *cxstat)
107 {
108 int ret = 0;
109 int max_cx_num = 0;
111 ret = xc_pm_get_max_cx(xc_handle, cpuid, &max_cx_num);
112 if ( ret )
113 return errno;
115 if ( !cxstat )
116 return -EINVAL;
118 cxstat->triggers = malloc(max_cx_num * sizeof(uint64_t));
119 if ( !cxstat->triggers )
120 return -ENOMEM;
121 cxstat->residencies = malloc(max_cx_num * sizeof(uint64_t));
122 if ( !cxstat->residencies )
123 {
124 free(cxstat->triggers);
125 return -ENOMEM;
126 }
128 ret = xc_pm_get_cxstat(xc_handle, cpuid, cxstat);
129 if( ret )
130 {
131 int temp = errno;
132 free(cxstat->triggers);
133 free(cxstat->residencies);
134 cxstat->triggers = NULL;
135 cxstat->residencies = NULL;
136 return temp;
137 }
139 return 0;
140 }
142 static int show_max_cstate(xc_interface *xc_handle)
143 {
144 int ret = 0;
145 uint32_t value;
147 if ( (ret = xc_get_cpuidle_max_cstate(xc_handle, &value)) )
148 return ret;
150 printf("Max C-state: C%d\n\n", value);
151 return 0;
152 }
154 static int show_cxstat_by_cpuid(xc_interface *xc_handle, int cpuid)
155 {
156 int ret = 0;
157 struct xc_cx_stat cxstatinfo;
159 ret = get_cxstat_by_cpuid(xc_handle, cpuid, &cxstatinfo);
160 if ( ret )
161 return ret;
163 print_cxstat(cpuid, &cxstatinfo);
165 free(cxstatinfo.triggers);
166 free(cxstatinfo.residencies);
167 return 0;
168 }
170 void cxstat_func(int argc, char *argv[])
171 {
172 int cpuid = -1;
174 if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
175 cpuid = -1;
177 if ( cpuid >= max_cpu_nr )
178 cpuid = -1;
180 show_max_cstate(xc_handle);
182 if ( cpuid < 0 )
183 {
184 /* show cxstates on all cpus */
185 int i;
186 for ( i = 0; i < max_cpu_nr; i++ )
187 if ( show_cxstat_by_cpuid(xc_handle, i) == -ENODEV )
188 break;
189 }
190 else
191 show_cxstat_by_cpuid(xc_handle, cpuid);
192 }
194 static void print_pxstat(int cpuid, struct xc_px_stat *pxstat)
195 {
196 int i;
198 printf("cpu id : %d\n", cpuid);
199 printf("total P-states : %d\n", pxstat->total);
200 printf("usable P-states : %d\n", pxstat->usable);
201 printf("current frequency : %"PRIu64" MHz\n",
202 pxstat->pt[pxstat->cur].freq);
203 for ( i = 0; i < pxstat->total; i++ )
204 {
205 if ( pxstat->cur == i )
206 printf("*P%d", i);
207 else
208 printf("P%d ", i);
209 printf(" : freq [%04"PRIu64" MHz]\n",
210 pxstat->pt[i].freq);
211 printf(" transition [%020"PRIu64"]\n",
212 pxstat->pt[i].count);
213 printf(" residency [%020"PRIu64" ms]\n",
214 pxstat->pt[i].residency/1000000UL);
215 }
216 printf("\n");
217 }
219 /* show cpu frequency information on CPU cpuid */
220 static int get_pxstat_by_cpuid(xc_interface *xc_handle, int cpuid, struct xc_px_stat *pxstat)
221 {
222 int ret = 0;
223 int max_px_num = 0;
225 ret = xc_pm_get_max_px(xc_handle, cpuid, &max_px_num);
226 if ( ret )
227 return errno;
229 if ( !pxstat)
230 return -EINVAL;
232 pxstat->trans_pt = malloc(max_px_num * max_px_num *
233 sizeof(uint64_t));
234 if ( !pxstat->trans_pt )
235 return -ENOMEM;
236 pxstat->pt = malloc(max_px_num * sizeof(struct xc_px_val));
237 if ( !pxstat->pt )
238 {
239 free(pxstat->trans_pt);
240 return -ENOMEM;
241 }
243 ret = xc_pm_get_pxstat(xc_handle, cpuid, pxstat);
244 if( ret )
245 {
246 int temp = errno;
247 free(pxstat->trans_pt);
248 free(pxstat->pt);
249 pxstat->trans_pt = NULL;
250 pxstat->pt = NULL;
251 return temp;
252 }
254 return 0;
255 }
257 /* show cpu actual average freq information on CPU cpuid */
258 static int get_avgfreq_by_cpuid(xc_interface *xc_handle, int cpuid, int *avgfreq)
259 {
260 int ret = 0;
262 ret = xc_get_cpufreq_avgfreq(xc_handle, cpuid, avgfreq);
263 if ( ret )
264 {
265 return errno;
266 }
268 return 0;
269 }
271 static int show_pxstat_by_cpuid(xc_interface *xc_handle, int cpuid)
272 {
273 int ret = 0;
274 struct xc_px_stat pxstatinfo;
276 ret = get_pxstat_by_cpuid(xc_handle, cpuid, &pxstatinfo);
277 if ( ret )
278 return ret;
280 print_pxstat(cpuid, &pxstatinfo);
282 free(pxstatinfo.trans_pt);
283 free(pxstatinfo.pt);
284 return 0;
285 }
287 void pxstat_func(int argc, char *argv[])
288 {
289 int cpuid = -1;
291 if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
292 cpuid = -1;
294 if ( cpuid >= max_cpu_nr )
295 cpuid = -1;
297 if ( cpuid < 0 )
298 {
299 /* show pxstates on all cpus */
300 int i;
301 for ( i = 0; i < max_cpu_nr; i++ )
302 if ( show_pxstat_by_cpuid(xc_handle, i) == -ENODEV )
303 break;
304 }
305 else
306 show_pxstat_by_cpuid(xc_handle, cpuid);
307 }
309 static uint64_t usec_start, usec_end;
310 static struct xc_cx_stat *cxstat, *cxstat_start, *cxstat_end;
311 static struct xc_px_stat *pxstat, *pxstat_start, *pxstat_end;
312 static int *avgfreq;
313 static uint64_t *sum, *sum_cx, *sum_px;
315 static void signal_int_handler(int signo)
316 {
317 int i, j, k, ret;
318 struct timeval tv;
319 int cx_cap = 0, px_cap = 0;
320 DECLARE_HYPERCALL_BUFFER(uint32_t, cpu_to_core);
321 DECLARE_HYPERCALL_BUFFER(uint32_t, cpu_to_socket);
322 DECLARE_HYPERCALL_BUFFER(uint32_t, cpu_to_node);
323 xc_topologyinfo_t info = { 0 };
325 cpu_to_core = xc_hypercall_buffer_alloc(xc_handle, cpu_to_core, sizeof(*cpu_to_core) * MAX_NR_CPU);
326 cpu_to_socket = xc_hypercall_buffer_alloc(xc_handle, cpu_to_socket, sizeof(*cpu_to_socket) * MAX_NR_CPU);
327 cpu_to_node = xc_hypercall_buffer_alloc(xc_handle, cpu_to_node, sizeof(*cpu_to_node) * MAX_NR_CPU);
329 if ( cpu_to_core == NULL || cpu_to_socket == NULL || cpu_to_node == NULL )
330 {
331 fprintf(stderr, "failed to allocate hypercall buffers\n");
332 goto out;
333 }
335 if ( gettimeofday(&tv, NULL) == -1 )
336 {
337 fprintf(stderr, "failed to get timeofday\n");
338 goto out ;
339 }
340 usec_end = tv.tv_sec * 1000000UL + tv.tv_usec;
342 if ( get_cxstat_by_cpuid(xc_handle, 0, NULL) != -ENODEV )
343 {
344 cx_cap = 1;
345 for ( i = 0; i < max_cpu_nr; i++ )
346 if ( !get_cxstat_by_cpuid(xc_handle, i, &cxstat_end[i]) )
347 for ( j = 0; j < cxstat_end[i].nr; j++ )
348 sum_cx[i] += cxstat_end[i].residencies[j] -
349 cxstat_start[i].residencies[j];
350 }
352 if ( get_pxstat_by_cpuid(xc_handle, 0, NULL) != -ENODEV )
353 {
354 px_cap = 1;
355 for ( i = 0; i < max_cpu_nr; i++ )
356 if ( !get_pxstat_by_cpuid(xc_handle, i , &pxstat_end[i]) )
357 for ( j = 0; j < pxstat_end[i].total; j++ )
358 sum_px[i] += pxstat_end[i].pt[j].residency -
359 pxstat_start[i].pt[j].residency;
360 }
362 for ( i = 0; i < max_cpu_nr; i++ )
363 get_avgfreq_by_cpuid(xc_handle, i, &avgfreq[i]);
365 printf("Elapsed time (ms): %"PRIu64"\n", (usec_end - usec_start) / 1000UL);
366 for ( i = 0; i < max_cpu_nr; i++ )
367 {
368 uint64_t res, triggers;
369 double avg_res;
371 printf("\nCPU%d:\tResidency(ms)\t\tAvg Res(ms)\n",i);
372 if ( cx_cap && sum_cx[i] > 0 )
373 {
374 for ( j = 0; j < cxstat_end[i].nr; j++ )
375 {
376 res = cxstat_end[i].residencies[j] -
377 cxstat_start[i].residencies[j];
378 triggers = cxstat_end[i].triggers[j] -
379 cxstat_start[i].triggers[j];
380 avg_res = (triggers==0) ? 0: (double)res/triggers/1000000.0;
381 printf(" C%d\t%"PRIu64"\t(%5.2f%%)\t%.2f\n", j, res/1000000UL,
382 100 * res / (double)sum_cx[i], avg_res );
383 }
384 printf("\n");
385 }
386 if ( px_cap && sum_px[i]>0 )
387 {
388 for ( j = 0; j < pxstat_end[i].total; j++ )
389 {
390 res = pxstat_end[i].pt[j].residency -
391 pxstat_start[i].pt[j].residency;
392 printf(" P%d\t%"PRIu64"\t(%5.2f%%)\n", j,
393 res / 1000000UL, 100UL * res / (double)sum_px[i]);
394 }
395 }
396 }
398 set_xen_guest_handle(info.cpu_to_core, cpu_to_core);
399 set_xen_guest_handle(info.cpu_to_socket, cpu_to_socket);
400 set_xen_guest_handle(info.cpu_to_node, cpu_to_node);
401 info.max_cpu_index = MAX_NR_CPU - 1;
403 ret = xc_topologyinfo(xc_handle, &info);
404 if ( !ret )
405 {
406 uint32_t socket_ids[MAX_NR_CPU];
407 uint32_t core_ids[MAX_NR_CPU];
408 uint32_t socket_nr = 0;
409 uint32_t core_nr = 0;
411 if ( info.max_cpu_index > MAX_NR_CPU - 1 )
412 info.max_cpu_index = MAX_NR_CPU - 1;
413 /* check validity */
414 for ( i = 0; i <= info.max_cpu_index; i++ )
415 {
416 if ( cpu_to_core[i] == INVALID_TOPOLOGY_ID ||
417 cpu_to_socket[i] == INVALID_TOPOLOGY_ID )
418 break;
419 }
420 if ( i > info.max_cpu_index )
421 {
422 /* find socket nr & core nr per socket */
423 for ( i = 0; i <= info.max_cpu_index; i++ )
424 {
425 for ( j = 0; j < socket_nr; j++ )
426 if ( cpu_to_socket[i] == socket_ids[j] )
427 break;
428 if ( j == socket_nr )
429 {
430 socket_ids[j] = cpu_to_socket[i];
431 socket_nr++;
432 }
434 for ( j = 0; j < core_nr; j++ )
435 if ( cpu_to_core[i] == core_ids[j] )
436 break;
437 if ( j == core_nr )
438 {
439 core_ids[j] = cpu_to_core[i];
440 core_nr++;
441 }
442 }
444 /* print out CC? and PC? */
445 for ( i = 0; i < socket_nr; i++ )
446 {
447 uint64_t res;
448 for ( j = 0; j <= info.max_cpu_index; j++ )
449 {
450 if ( cpu_to_socket[j] == socket_ids[i] )
451 break;
452 }
453 printf("Socket %d\n", socket_ids[i]);
454 res = cxstat_end[j].pc3 - cxstat_start[j].pc3;
455 printf("\tPC3\t%"PRIu64" ms\t%.2f%%\n", res / 1000000UL,
456 100UL * res / (double)sum_cx[j]);
457 res = cxstat_end[j].pc6 - cxstat_start[j].pc6;
458 printf("\tPC6\t%"PRIu64" ms\t%.2f%%\n", res / 1000000UL,
459 100UL * res / (double)sum_cx[j]);
460 res = cxstat_end[j].pc7 - cxstat_start[j].pc7;
461 printf("\tPC7\t%"PRIu64" ms\t%.2f%%\n", res / 1000000UL,
462 100UL * res / (double)sum_cx[j]);
463 for ( k = 0; k < core_nr; k++ )
464 {
465 for ( j = 0; j <= info.max_cpu_index; j++ )
466 {
467 if ( cpu_to_socket[j] == socket_ids[i] &&
468 cpu_to_core[j] == core_ids[k] )
469 break;
470 }
471 printf("\t Core %d CPU %d\n", core_ids[k], j);
472 res = cxstat_end[j].cc3 - cxstat_start[j].cc3;
473 printf("\t\tCC3\t%"PRIu64" ms\t%.2f%%\n", res / 1000000UL,
474 100UL * res / (double)sum_cx[j]);
475 res = cxstat_end[j].cc6 - cxstat_start[j].cc6;
476 printf("\t\tCC6\t%"PRIu64" ms\t%.2f%%\n", res / 1000000UL,
477 100UL * res / (double)sum_cx[j]);
478 printf("\n");
480 }
481 }
482 }
483 printf(" Avg freq\t%d\tKHz\n", avgfreq[i]);
484 }
486 /* some clean up and then exits */
487 for ( i = 0; i < 2 * max_cpu_nr; i++ )
488 {
489 free(cxstat[i].triggers);
490 free(cxstat[i].residencies);
491 free(pxstat[i].trans_pt);
492 free(pxstat[i].pt);
493 }
494 free(cxstat);
495 free(pxstat);
496 free(sum);
497 free(avgfreq);
498 out:
499 xc_hypercall_buffer_free(xc_handle, cpu_to_core);
500 xc_hypercall_buffer_free(xc_handle, cpu_to_socket);
501 xc_hypercall_buffer_free(xc_handle, cpu_to_node);
502 xc_interface_close(xc_handle);
503 exit(0);
504 }
506 void start_gather_func(int argc, char *argv[])
507 {
508 int i;
509 struct timeval tv;
510 int timeout = 0;
512 if ( argc == 1 )
513 {
514 sscanf(argv[0], "%d", &timeout);
515 if ( timeout <= 0 )
516 fprintf(stderr, "failed to set timeout seconds, falling back...\n");
517 else
518 printf("Timeout set to %d seconds\n", timeout);
519 }
521 if ( gettimeofday(&tv, NULL) == -1 )
522 {
523 fprintf(stderr, "failed to get timeofday\n");
524 return ;
525 }
526 usec_start = tv.tv_sec * 1000000UL + tv.tv_usec;
528 sum = malloc(sizeof(uint64_t) * 2 * max_cpu_nr);
529 if ( sum == NULL )
530 return ;
531 cxstat = malloc(sizeof(struct xc_cx_stat) * 2 * max_cpu_nr);
532 if ( cxstat == NULL )
533 {
534 free(sum);
535 return ;
536 }
537 pxstat = malloc(sizeof(struct xc_px_stat) * 2 * max_cpu_nr);
538 if ( pxstat == NULL )
539 {
540 free(sum);
541 free(cxstat);
542 return ;
543 }
544 avgfreq = malloc(sizeof(int) * max_cpu_nr);
545 if ( avgfreq == NULL )
546 {
547 free(sum);
548 free(cxstat);
549 free(pxstat);
550 return ;
551 }
552 memset(sum, 0, sizeof(uint64_t) * 2 * max_cpu_nr);
553 memset(cxstat, 0, sizeof(struct xc_cx_stat) * 2 * max_cpu_nr);
554 memset(pxstat, 0, sizeof(struct xc_px_stat) * 2 * max_cpu_nr);
555 memset(avgfreq, 0, sizeof(int) * max_cpu_nr);
556 sum_cx = sum;
557 sum_px = sum + max_cpu_nr;
558 cxstat_start = cxstat;
559 cxstat_end = cxstat + max_cpu_nr;
560 pxstat_start = pxstat;
561 pxstat_end = pxstat + max_cpu_nr;
563 if ( get_cxstat_by_cpuid(xc_handle, 0, NULL) == -ENODEV &&
564 get_pxstat_by_cpuid(xc_handle, 0, NULL) == -ENODEV )
565 {
566 fprintf(stderr, "Xen cpu idle and frequency is disabled!\n");
567 return ;
568 }
570 for ( i = 0; i < max_cpu_nr; i++ )
571 {
572 get_cxstat_by_cpuid(xc_handle, i, &cxstat_start[i]);
573 get_pxstat_by_cpuid(xc_handle, i, &pxstat_start[i]);
574 get_avgfreq_by_cpuid(xc_handle, i, &avgfreq[i]);
575 }
577 if (signal(SIGINT, signal_int_handler) == SIG_ERR)
578 {
579 fprintf(stderr, "failed to set signal int handler\n");
580 free(sum);
581 free(pxstat);
582 free(cxstat);
583 free(avgfreq);
584 return ;
585 }
587 if ( timeout > 0 )
588 {
589 if ( signal(SIGALRM, signal_int_handler) == SIG_ERR )
590 {
591 fprintf(stderr, "failed to set signal alarm handler\n");
592 free(sum);
593 free(pxstat);
594 free(cxstat);
595 free(avgfreq);
596 return ;
597 }
598 alarm(timeout);
599 }
601 printf("Start sampling, waiting for CTRL-C or SIGINT or SIGALARM signal ...\n");
603 pause();
604 }
606 /* print out parameters about cpu frequency */
607 static void print_cpufreq_para(int cpuid, struct xc_get_cpufreq_para *p_cpufreq)
608 {
609 int i;
611 printf("cpu id : %d\n", cpuid);
613 printf("affected_cpus :");
614 for ( i = 0; i < p_cpufreq->cpu_num; i++ )
615 printf(" %d", p_cpufreq->affected_cpus[i]);
616 printf("\n");
618 printf("cpuinfo frequency : max [%u] min [%u] cur [%u]\n",
619 p_cpufreq->cpuinfo_max_freq,
620 p_cpufreq->cpuinfo_min_freq,
621 p_cpufreq->cpuinfo_cur_freq);
623 printf("scaling_driver : %s\n", p_cpufreq->scaling_driver);
625 printf("scaling_avail_gov : %s\n",
626 p_cpufreq->scaling_available_governors);
628 printf("current_governor : %s\n", p_cpufreq->scaling_governor);
629 if ( !strncmp(p_cpufreq->scaling_governor,
630 "userspace", CPUFREQ_NAME_LEN) )
631 {
632 printf(" userspace specific :\n");
633 printf(" scaling_setspeed : %u\n",
634 p_cpufreq->u.userspace.scaling_setspeed);
635 }
636 else if ( !strncmp(p_cpufreq->scaling_governor,
637 "ondemand", CPUFREQ_NAME_LEN) )
638 {
639 printf(" ondemand specific :\n");
640 printf(" sampling_rate : max [%u] min [%u] cur [%u]\n",
641 p_cpufreq->u.ondemand.sampling_rate_max,
642 p_cpufreq->u.ondemand.sampling_rate_min,
643 p_cpufreq->u.ondemand.sampling_rate);
644 printf(" up_threshold : %u\n",
645 p_cpufreq->u.ondemand.up_threshold);
646 }
648 printf("scaling_avail_freq :");
649 for ( i = 0; i < p_cpufreq->freq_num; i++ )
650 if ( p_cpufreq->scaling_available_frequencies[i] ==
651 p_cpufreq->scaling_cur_freq )
652 printf(" *%d", p_cpufreq->scaling_available_frequencies[i]);
653 else
654 printf(" %d", p_cpufreq->scaling_available_frequencies[i]);
655 printf("\n");
657 printf("scaling frequency : max [%u] min [%u] cur [%u]\n",
658 p_cpufreq->scaling_max_freq,
659 p_cpufreq->scaling_min_freq,
660 p_cpufreq->scaling_cur_freq);
661 if (p_cpufreq->turbo_enabled != CPUFREQ_TURBO_UNSUPPORTED) {
662 printf("turbo mode : ");
663 if (p_cpufreq->turbo_enabled == CPUFREQ_TURBO_ENABLED)
664 printf("enabled\n");
665 else
666 printf("disabled\n");
667 }
668 printf("\n");
669 }
671 /* show cpu frequency parameters information on CPU cpuid */
672 static int show_cpufreq_para_by_cpuid(xc_interface *xc_handle, int cpuid)
673 {
674 int ret = 0;
675 struct xc_get_cpufreq_para cpufreq_para, *p_cpufreq = &cpufreq_para;
677 p_cpufreq->cpu_num = 0;
678 p_cpufreq->freq_num = 0;
679 p_cpufreq->gov_num = 0;
680 p_cpufreq->affected_cpus = NULL;
681 p_cpufreq->scaling_available_frequencies = NULL;
682 p_cpufreq->scaling_available_governors = NULL;
683 p_cpufreq->turbo_enabled = 0;
685 do
686 {
687 free(p_cpufreq->affected_cpus);
688 free(p_cpufreq->scaling_available_frequencies);
689 free(p_cpufreq->scaling_available_governors);
691 p_cpufreq->affected_cpus = NULL;
692 p_cpufreq->scaling_available_frequencies = NULL;
693 p_cpufreq->scaling_available_governors = NULL;
695 if (!(p_cpufreq->affected_cpus =
696 malloc(p_cpufreq->cpu_num * sizeof(uint32_t))))
697 {
698 fprintf(stderr,
699 "[CPU%d] failed to malloc for affected_cpus\n",
700 cpuid);
701 ret = -ENOMEM;
702 goto out;
703 }
704 if (!(p_cpufreq->scaling_available_frequencies =
705 malloc(p_cpufreq->freq_num * sizeof(uint32_t))))
706 {
707 fprintf(stderr,
708 "[CPU%d] failed to malloc for scaling_available_frequencies\n",
709 cpuid);
710 ret = -ENOMEM;
711 goto out;
712 }
713 if (!(p_cpufreq->scaling_available_governors =
714 malloc(p_cpufreq->gov_num * CPUFREQ_NAME_LEN * sizeof(char))))
715 {
716 fprintf(stderr,
717 "[CPU%d] failed to malloc for scaling_available_governors\n",
718 cpuid);
719 ret = -ENOMEM;
720 goto out;
721 }
723 ret = xc_get_cpufreq_para(xc_handle, cpuid, p_cpufreq);
724 } while ( ret && errno == EAGAIN );
726 if ( ret == 0 )
727 print_cpufreq_para(cpuid, p_cpufreq);
728 else if ( errno == ENODEV )
729 {
730 ret = -ENODEV;
731 fprintf(stderr, "Xen cpufreq is not enabled!\n");
732 }
733 else
734 fprintf(stderr,
735 "[CPU%d] failed to get cpufreq parameter\n",
736 cpuid);
738 out:
739 free(p_cpufreq->scaling_available_governors);
740 free(p_cpufreq->scaling_available_frequencies);
741 free(p_cpufreq->affected_cpus);
743 return ret;
744 }
746 void cpufreq_para_func(int argc, char *argv[])
747 {
748 int cpuid = -1;
750 if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
751 cpuid = -1;
753 if ( cpuid >= max_cpu_nr )
754 cpuid = -1;
756 if ( cpuid < 0 )
757 {
758 /* show cpu freqency information on all cpus */
759 int i;
760 for ( i = 0; i < max_cpu_nr; i++ )
761 if ( show_cpufreq_para_by_cpuid(xc_handle, i) == -ENODEV )
762 break;
763 }
764 else
765 show_cpufreq_para_by_cpuid(xc_handle, cpuid);
766 }
768 void scaling_max_freq_func(int argc, char *argv[])
769 {
770 int cpuid = -1, freq = -1;
772 if ( (argc >= 2 && (sscanf(argv[1], "%d", &freq) != 1 ||
773 sscanf(argv[0], "%d", &cpuid) != 1)) ||
774 (argc == 1 && sscanf(argv[0], "%d", &freq) != 1 ) ||
775 argc == 0 )
776 {
777 fprintf(stderr, "failed to set scaling max freq\n");
778 return ;
779 }
781 if ( cpuid < 0 )
782 {
783 int i;
784 for ( i = 0; i < max_cpu_nr; i++ )
785 if ( xc_set_cpufreq_para(xc_handle, i, SCALING_MAX_FREQ, freq) )
786 fprintf(stderr, "[CPU%d] failed to set scaling max freq\n", i);
787 }
788 else
789 {
790 if ( xc_set_cpufreq_para(xc_handle, cpuid, SCALING_MAX_FREQ, freq) )
791 fprintf(stderr, "failed to set scaling max freq\n");
792 }
793 }
795 void scaling_min_freq_func(int argc, char *argv[])
796 {
797 int cpuid = -1, freq = -1;
799 if ( (argc >= 2 && (sscanf(argv[1], "%d", &freq) != 1 ||
800 sscanf(argv[0], "%d", &cpuid) != 1) ) ||
801 (argc == 1 && sscanf(argv[0], "%d", &freq) != 1 ) ||
802 argc == 0 )
803 {
804 fprintf(stderr, "failed to set scaling min freq\n");
805 return ;
806 }
808 if ( cpuid < 0 )
809 {
810 int i;
811 for ( i = 0; i < max_cpu_nr; i++ )
812 if ( xc_set_cpufreq_para(xc_handle, i, SCALING_MIN_FREQ, freq) )
813 fprintf(stderr, "[CPU%d] failed to set scaling min freq\n", i);
814 }
815 else
816 {
817 if ( xc_set_cpufreq_para(xc_handle, cpuid, SCALING_MIN_FREQ, freq) )
818 fprintf(stderr, "failed to set scaling min freq\n");
819 }
820 }
822 void scaling_speed_func(int argc, char *argv[])
823 {
824 int cpuid = -1, speed = -1;
826 if ( (argc >= 2 && (sscanf(argv[1], "%d", &speed) != 1 ||
827 sscanf(argv[0], "%d", &cpuid) != 1) ) ||
828 (argc == 1 && sscanf(argv[0], "%d", &speed) != 1 ) ||
829 argc == 0 )
830 {
831 fprintf(stderr, "failed to set scaling speed\n");
832 return ;
833 }
835 if ( cpuid < 0 )
836 {
837 int i;
838 for ( i = 0; i < max_cpu_nr; i++ )
839 if ( xc_set_cpufreq_para(xc_handle, i, SCALING_SETSPEED, speed) )
840 fprintf(stderr, "[CPU%d] failed to set scaling speed\n", i);
841 }
842 else
843 {
844 if ( xc_set_cpufreq_para(xc_handle, cpuid, SCALING_SETSPEED, speed) )
845 fprintf(stderr, "failed to set scaling speed\n");
846 }
847 }
849 void scaling_sampling_rate_func(int argc, char *argv[])
850 {
851 int cpuid = -1, rate = -1;
853 if ( (argc >= 2 && (sscanf(argv[1], "%d", &rate) != 1 ||
854 sscanf(argv[0], "%d", &cpuid) != 1) ) ||
855 (argc == 1 && sscanf(argv[0], "%d", &rate) != 1 ) ||
856 argc == 0 )
857 {
858 fprintf(stderr, "failed to set scaling sampling rate\n");
859 return ;
860 }
862 if ( cpuid < 0 )
863 {
864 int i;
865 for ( i = 0; i < max_cpu_nr; i++ )
866 if ( xc_set_cpufreq_para(xc_handle, i, SAMPLING_RATE, rate) )
867 fprintf(stderr,
868 "[CPU%d] failed to set scaling sampling rate\n", i);
869 }
870 else
871 {
872 if ( xc_set_cpufreq_para(xc_handle, cpuid, SAMPLING_RATE, rate) )
873 fprintf(stderr, "failed to set scaling sampling rate\n");
874 }
875 }
877 void scaling_up_threshold_func(int argc, char *argv[])
878 {
879 int cpuid = -1, threshold = -1;
881 if ( (argc >= 2 && (sscanf(argv[1], "%d", &threshold) != 1 ||
882 sscanf(argv[0], "%d", &cpuid) != 1) ) ||
883 (argc == 1 && sscanf(argv[0], "%d", &threshold) != 1 ) ||
884 argc == 0 )
885 {
886 fprintf(stderr, "failed to set up scaling threshold\n");
887 return ;
888 }
890 if ( cpuid < 0 )
891 {
892 int i;
893 for ( i = 0; i < max_cpu_nr; i++ )
894 if ( xc_set_cpufreq_para(xc_handle, i, UP_THRESHOLD, threshold) )
895 fprintf(stderr,
896 "[CPU%d] failed to set up scaling threshold\n", i);
897 }
898 else
899 {
900 if ( xc_set_cpufreq_para(xc_handle, cpuid, UP_THRESHOLD, threshold) )
901 fprintf(stderr, "failed to set up scaling threshold\n");
902 }
903 }
905 void scaling_governor_func(int argc, char *argv[])
906 {
907 int cpuid = -1;
908 char *name = NULL;
910 if ( argc >= 2 )
911 {
912 name = strdup(argv[1]);
913 if ( name == NULL )
914 goto out;
915 if ( sscanf(argv[0], "%d", &cpuid) != 1 )
916 {
917 free(name);
918 goto out;
919 }
920 }
921 else if ( argc > 0 )
922 {
923 name = strdup(argv[0]);
924 if ( name == NULL )
925 goto out;
926 }
927 else
928 goto out;
930 if ( cpuid < 0 )
931 {
932 int i;
933 for ( i = 0; i < max_cpu_nr; i++ )
934 if ( xc_set_cpufreq_gov(xc_handle, i, name) )
935 fprintf(stderr, "[CPU%d] failed to set governor name\n", i);
936 }
937 else
938 {
939 if ( xc_set_cpufreq_gov(xc_handle, cpuid, name) )
940 fprintf(stderr, "failed to set governor name\n");
941 }
943 free(name);
944 return ;
945 out:
946 fprintf(stderr, "failed to set governor name\n");
947 }
949 void cpu_topology_func(int argc, char *argv[])
950 {
951 DECLARE_HYPERCALL_BUFFER(uint32_t, cpu_to_core);
952 DECLARE_HYPERCALL_BUFFER(uint32_t, cpu_to_socket);
953 DECLARE_HYPERCALL_BUFFER(uint32_t, cpu_to_node);
954 xc_topologyinfo_t info = { 0 };
955 int i;
957 cpu_to_core = xc_hypercall_buffer_alloc(xc_handle, cpu_to_core, sizeof(*cpu_to_core) * MAX_NR_CPU);
958 cpu_to_socket = xc_hypercall_buffer_alloc(xc_handle, cpu_to_socket, sizeof(*cpu_to_socket) * MAX_NR_CPU);
959 cpu_to_node = xc_hypercall_buffer_alloc(xc_handle, cpu_to_node, sizeof(*cpu_to_node) * MAX_NR_CPU);
961 if ( cpu_to_core == NULL || cpu_to_socket == NULL || cpu_to_node == NULL )
962 {
963 fprintf(stderr, "failed to allocate hypercall buffers\n");
964 goto out;
965 }
967 set_xen_guest_handle(info.cpu_to_core, cpu_to_core);
968 set_xen_guest_handle(info.cpu_to_socket, cpu_to_socket);
969 set_xen_guest_handle(info.cpu_to_node, cpu_to_node);
970 info.max_cpu_index = MAX_NR_CPU-1;
972 if ( xc_topologyinfo(xc_handle, &info) )
973 {
974 printf("Can not get Xen CPU topology: %d\n", errno);
975 goto out;
976 }
978 if ( info.max_cpu_index > (MAX_NR_CPU-1) )
979 info.max_cpu_index = MAX_NR_CPU-1;
981 printf("CPU\tcore\tsocket\tnode\n");
982 for ( i = 0; i <= info.max_cpu_index; i++ )
983 {
984 if ( cpu_to_core[i] == INVALID_TOPOLOGY_ID )
985 continue;
986 printf("CPU%d\t %d\t %d\t %d\n",
987 i, cpu_to_core[i], cpu_to_socket[i], cpu_to_node[i]);
988 }
989 out:
990 xc_hypercall_buffer_free(xc_handle, cpu_to_core);
991 xc_hypercall_buffer_free(xc_handle, cpu_to_socket);
992 xc_hypercall_buffer_free(xc_handle, cpu_to_node);
993 }
995 void set_sched_smt_func(int argc, char *argv[])
996 {
997 int value, rc;
999 if (argc != 1){
1000 show_help();
1001 exit(-1);
1004 if ( !strncmp(argv[0], "disable", sizeof("disable")) )
1006 value = 0;
1008 else if ( !strncmp(argv[0], "enable", sizeof("enable")) )
1010 value = 1;
1012 else
1014 show_help();
1015 exit(-1);
1018 rc = xc_set_sched_opt_smt(xc_handle, value);
1019 printf("%s sched_smt_power_savings %s\n", argv[0],
1020 rc? "failed":"succeeded" );
1022 return;
1025 void set_vcpu_migration_delay_func(int argc, char *argv[])
1027 int value;
1028 int rc;
1030 if (argc != 1){
1031 show_help();
1032 exit(-1);
1035 value = atoi(argv[0]);
1037 if (value < 0)
1039 printf("Please try non-negative vcpu migration delay\n");
1040 exit(-1);
1043 rc = xc_set_vcpu_migration_delay(xc_handle, value);
1044 printf("%s to set vcpu migration delay to %d us\n",
1045 rc? "Fail":"Succeed", value );
1047 return;
1050 void get_vcpu_migration_delay_func(int argc, char *argv[])
1052 uint32_t value;
1053 int rc;
1055 if (argc != 0){
1056 show_help();
1057 exit(-1);
1060 rc = xc_get_vcpu_migration_delay(xc_handle, &value);
1061 if (!rc)
1063 printf("Schduler vcpu migration delay is %d us\n", value);
1065 else
1067 printf("Failed to get scheduler vcpu migration delay, errno=%d\n", errno);
1070 return;
1073 void set_max_cstate_func(int argc, char *argv[])
1075 int value, rc;
1077 if ( argc != 1 || sscanf(argv[0], "%d", &value) != 1 || value < 0 )
1079 show_help();
1080 exit(-1);
1083 rc = xc_set_cpuidle_max_cstate(xc_handle, (uint32_t)value);
1084 printf("set max_cstate to C%d %s\n", value,
1085 rc? "failed":"succeeded" );
1087 return;
1090 void enable_turbo_mode(int argc, char *argv[])
1092 int cpuid = -1;
1094 if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
1095 cpuid = -1;
1097 if ( cpuid >= max_cpu_nr )
1098 cpuid = -1;
1100 if ( cpuid < 0 )
1102 /* enable turbo modes on all cpus,
1103 * only make effects on dbs governor */
1104 int i;
1105 for ( i = 0; i < max_cpu_nr; i++ )
1106 xc_enable_turbo(xc_handle, i);
1108 else
1109 xc_enable_turbo(xc_handle, cpuid);
1112 void disable_turbo_mode(int argc, char *argv[])
1114 int cpuid = -1;
1116 if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 )
1117 cpuid = -1;
1119 if ( cpuid >= max_cpu_nr )
1120 cpuid = -1;
1122 if ( cpuid < 0 )
1124 /* disable turbo modes on all cpus,
1125 * only make effects on dbs governor */
1126 int i;
1127 for ( i = 0; i < max_cpu_nr; i++ )
1128 xc_disable_turbo(xc_handle, i);
1130 else
1131 xc_disable_turbo(xc_handle, cpuid);
1134 struct {
1135 const char *name;
1136 void (*function)(int argc, char *argv[]);
1137 } main_options[] = {
1138 { "help", help_func },
1139 { "get-cpuidle-states", cxstat_func },
1140 { "get-cpufreq-states", pxstat_func },
1141 { "start", start_gather_func },
1142 { "get-cpufreq-para", cpufreq_para_func },
1143 { "set-scaling-maxfreq", scaling_max_freq_func },
1144 { "set-scaling-minfreq", scaling_min_freq_func },
1145 { "set-scaling-governor", scaling_governor_func },
1146 { "set-scaling-speed", scaling_speed_func },
1147 { "set-sampling-rate", scaling_sampling_rate_func },
1148 { "set-up-threshold", scaling_up_threshold_func },
1149 { "get-cpu-topology", cpu_topology_func},
1150 { "set-sched-smt", set_sched_smt_func},
1151 { "get-vcpu-migration-delay", get_vcpu_migration_delay_func},
1152 { "set-vcpu-migration-delay", set_vcpu_migration_delay_func},
1153 { "set-max-cstate", set_max_cstate_func},
1154 { "enable-turbo-mode", enable_turbo_mode },
1155 { "disable-turbo-mode", disable_turbo_mode },
1156 };
1158 int main(int argc, char *argv[])
1160 int i, ret = 0;
1161 xc_physinfo_t physinfo = { 0 };
1162 int nr_matches = 0;
1163 int matches_main_options[ARRAY_SIZE(main_options)];
1165 if ( argc < 2 )
1167 show_help();
1168 return 0;
1171 xc_handle = xc_interface_open(0,0,0);
1172 if ( !xc_handle )
1174 fprintf(stderr, "failed to get the handler\n");
1175 return 0;
1178 ret = xc_physinfo(xc_handle, &physinfo);
1179 if ( ret )
1181 fprintf(stderr, "failed to get the processor information\n");
1182 xc_interface_close(xc_handle);
1183 return 0;
1185 max_cpu_nr = physinfo.nr_cpus;
1187 /* calculate how many options match with user's input */
1188 for ( i = 0; i < ARRAY_SIZE(main_options); i++ )
1189 if ( !strncmp(main_options[i].name, argv[1], strlen(argv[1])) )
1190 matches_main_options[nr_matches++] = i;
1192 if ( nr_matches > 1 )
1194 fprintf(stderr, "Ambigious options: ");
1195 for ( i = 0; i < nr_matches; i++ )
1196 fprintf(stderr, " %s", main_options[matches_main_options[i]].name);
1197 fprintf(stderr, "\n");
1199 else if ( nr_matches == 1 )
1200 /* dispatch to the corresponding function handler */
1201 main_options[matches_main_options[0]].function(argc - 2, argv + 2);
1202 else
1203 show_help();
1205 xc_interface_close(xc_handle);
1206 return 0;