diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-09-25 10:21:40 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-09-25 10:21:40 +0100 |
commit | 876bb8d63988abd670aa94b786e7d50779683b3b (patch) | |
tree | 5c70c0b27eca528129c7539f57e0be7edacb7b45 /tools/misc/xenpm.c | |
parent | 391c70529c984140e767ab3f55b8728046e710e6 (diff) | |
download | xen-876bb8d63988abd670aa94b786e7d50779683b3b.tar.gz xen-876bb8d63988abd670aa94b786e7d50779683b3b.tar.bz2 xen-876bb8d63988abd670aa94b786e7d50779683b3b.zip |
x86: Add xenpm utility to list CPU power info.
Signed-off-by: Lu Guanqun <guanqun.lu@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Diffstat (limited to 'tools/misc/xenpm.c')
-rw-r--r-- | tools/misc/xenpm.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/tools/misc/xenpm.c b/tools/misc/xenpm.c new file mode 100644 index 0000000000..b705f0a6fa --- /dev/null +++ b/tools/misc/xenpm.c @@ -0,0 +1,197 @@ +/* + * xenpm.c: list the power information of the available processors + * Copyright (c) 2008, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <getopt.h> +#include <errno.h> + +#include <xenctrl.h> +#include <inttypes.h> + +int main(int argc, char **argv) +{ + int xc_fd; + int i, j, ret = 0; + int cinfo = 0, pinfo = 0; + int ch; + xc_physinfo_t physinfo = { 0 }; + + while ( (ch = getopt(argc, argv, "cp")) != -1 ) + { + switch ( ch ) + { + case 'c': + cinfo = 1; + break; + case 'p': + pinfo = 1; + break; + default: + fprintf(stderr, "%s [-p] [-c]\n", argv[0]); + return -1; + } + } + + if ( !cinfo && !pinfo ) + { + cinfo = 1; + pinfo = 1; + } + + xc_fd = xc_interface_open(); + if ( xc_fd < 0 ) + { + fprintf(stderr, "failed to get the handler\n"); + return xc_fd; + } + + ret = xc_physinfo(xc_fd, &physinfo); + if ( ret ) + { + fprintf(stderr, "failed to get the processor information\n"); + xc_interface_close(xc_fd); + return ret; + } + + /* print out the C state information */ + if ( cinfo ) + { + int max_cx_num = 0; + struct xc_cx_stat cxstatinfo, *cxstat = &cxstatinfo; + + for ( i = 0; i < physinfo.nr_cpus; i++ ) + { + ret = xc_pm_get_max_cx(xc_fd, i, &max_cx_num); + if ( ret ) + { + if ( errno == ENODEV ) + fprintf(stderr, "Xen cpuidle is not enabled!\n"); + else + fprintf(stderr, "failed to get max C-state\n"); + + break; + } + + cxstat->triggers = malloc(max_cx_num * sizeof(uint64_t)); + if ( !cxstat->triggers ) + { + fprintf(stderr, "failed to malloc for C-states triggers\n"); + break; + } + cxstat->residencies = malloc(max_cx_num * sizeof(uint64_t)); + if ( !cxstat->residencies ) + { + fprintf(stderr, "failed to malloc for C-states residencies\n"); + free(cxstat->triggers); + break; + } + + ret = xc_pm_get_cxstat(xc_fd, i, cxstat); + if( ret ) + { + fprintf(stderr, "failed to get C-states statistics information\n"); + free(cxstat->triggers); + free(cxstat->residencies); + break; + } + + printf("cpu id : %d\n", i); + printf("total C-states : %d\n", cxstat->nr); + printf("idle time(ms) : %"PRIu64"\n", cxstat->idle_time/1000000UL); + for ( j = 0; j < cxstat->nr; j++ ) + { + printf("C%d : transition [%020"PRIu64"]\n", + j, cxstat->triggers[j]); + printf(" residency [%020"PRIu64" ms]\n", + cxstat->residencies[j]*1000000UL/3579/1000000UL); + } + + free(cxstat->triggers); + free(cxstat->residencies); + + printf("\n"); + } + } + + /* print out P state information */ + if ( pinfo ) + { + int max_px_num = 0; + struct xc_px_stat pxstatinfo, *pxstat = &pxstatinfo; + + for ( i = 0; i < physinfo.nr_cpus; i++ ) + { + ret = xc_pm_get_max_px(xc_fd, i, &max_px_num); + if ( ret ) { + if ( errno == ENODEV ) + printf("Xen cpufreq is not enabled!\n"); + else + fprintf(stderr, "failed to get max P-state\n"); + + break; + } + + pxstat->trans_pt = malloc(max_px_num * max_px_num * sizeof(uint64_t)); + if ( !pxstat->trans_pt ) + { + fprintf(stderr, "failed to malloc for P-states transition table\n"); + break; + } + pxstat->pt = malloc(max_px_num * sizeof(struct xc_px_val)); + if ( !pxstat->pt ) + { + fprintf(stderr, "failed to malloc for P-states table\n"); + free(pxstat->pt); + break; + } + + ret = xc_pm_get_pxstat(xc_fd, 0, pxstat); + if( ret ) { + fprintf(stderr, "failed to get P-states statistics information\n"); + free(pxstat->trans_pt); + free(pxstat->pt); + break; + } + + printf("cpu id : %d\n", i); + printf("total P-states : %d\n", pxstat->total); + printf("usable P-states : %d\n", pxstat->usable); + printf("current frequency : %"PRIu64" MHz\n", pxstat->pt[pxstat->cur].freq); + for ( j = 0; j < pxstat->total; j++ ) + { + if ( pxstat->cur == j ) + printf("*P%d", j); + else + printf("P%d ", j); + printf(" : freq [%04"PRIu64" MHz]\n", pxstat->pt[j].freq); + printf(" transition [%020"PRIu64"]\n", pxstat->pt[j].count); + printf(" residency [%020"PRIu64" ms]\n", pxstat->pt[j].residency/1000000UL); + } + + free(pxstat->trans_pt); + free(pxstat->pt); + + printf("\n"); + } + } + + xc_interface_close(xc_fd); + return ret; +} + |