ia64/xen-unstable

changeset 18936:a76b4e00e186

xenpm: add cpu frequency control interface, through which user can
tune the parameters manually.

Now, xenpm can be invoked with the following options:
Usage:
xenpm get-cpuidle-states [cpuid]: list cpu idle information on
CPU cpuid or all CPUs.
xenpm get-cpufreq-states [cpuid]: list cpu frequency
information on CPU cpuid or all CPUs.
xenpm get-cpufreq-para [cpuid]: list cpu frequency information
on CPU cpuid or all CPUs.
xenpm set-scaling-maxfreq <cpuid> <HZ>: set max cpu frequency
<HZ> on CPU <cpuid>.
xenpm set-scaling-minfreq <cpuid> <HZ>: set min cpu frequency
<HZ> on CPU <cpuid>.
xenpm set-scaling-governor <cpuid> <name>: set scaling governor
on CPU <cpuid>.
xenpm set-scaling-speed <cpuid> <num>: set scaling speed on CPU
<cpuid>.
xenpm set-sampling-rate <cpuid> <num>: set sampling rate on CPU
<cpuid>.
xenpm set-up-threshold <cpuid> <num>: set up threshold on CPU
<cpuid>.

To ease the use of this tool, the shortcut option is supported,
i.e. `xenpm get-cpui' is equal to `xenpm get-cpuidle-states'.

Signed-off-by: Guanqun Lu <guanqun.lu@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Dec 16 13:14:25 2008 +0000 (2008-12-16)
parents fd720db48675
children 22e3666ee483
files tools/misc/xenpm.c
line diff
     1.1 --- a/tools/misc/xenpm.c	Tue Dec 16 12:04:13 2008 +0000
     1.2 +++ b/tools/misc/xenpm.c	Tue Dec 16 13:14:25 2008 +0000
     1.3 @@ -16,199 +16,591 @@
     1.4   * Place - Suite 330, Boston, MA 02111-1307 USA.
     1.5   */
     1.6  
     1.7 +/* to eliminate warning on `strndup' */
     1.8 +#define _GNU_SOURCE
     1.9 +
    1.10  #include <stdio.h>
    1.11  #include <stdlib.h>
    1.12 +#include <string.h>
    1.13  #include <getopt.h>
    1.14  #include <errno.h>
    1.15  
    1.16  #include <xenctrl.h>
    1.17  #include <inttypes.h>
    1.18  
    1.19 -int main(int argc, char **argv)
    1.20 +#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
    1.21 +
    1.22 +/* help message */
    1.23 +void show_help(void)
    1.24 +{
    1.25 +    fprintf(stderr,
    1.26 +            "Usage:\n"
    1.27 +            "       xenpm get-cpuidle-states [cpuid]: list cpu idle information on CPU cpuid or all CPUs.\n"
    1.28 +            "       xenpm get-cpufreq-states [cpuid]: list cpu frequency information on CPU cpuid or all CPUs.\n"
    1.29 +            "       xenpm get-cpufreq-para [cpuid]: list cpu frequency information on CPU cpuid or all CPUs.\n"
    1.30 +            "       xenpm set-scaling-maxfreq <cpuid> <HZ>: set max cpu frequency <HZ> on CPU <cpuid>.\n"
    1.31 +            "       xenpm set-scaling-minfreq <cpuid> <HZ>: set min cpu frequency <HZ> on CPU <cpuid>.\n"
    1.32 +            "       xenpm set-scaling-governor <cpuid> <name>: set scaling governor on CPU <cpuid>.\n"
    1.33 +            "       xenpm set-scaling-speed <cpuid> <num>: set scaling speed on CPU <cpuid>.\n"
    1.34 +            "       xenpm set-sampling-rate <cpuid> <num>: set sampling rate on CPU <cpuid>.\n"
    1.35 +            "       xenpm set-up-threshold <cpuid> <num>: set up threshold on CPU <cpuid>.\n");
    1.36 +}
    1.37 +
    1.38 +/* wrapper function */
    1.39 +int help_func(int xc_fd, int cpuid, uint32_t value)
    1.40 +{
    1.41 +    show_help();
    1.42 +    return 0;
    1.43 +}
    1.44 +
    1.45 +/* show cpu idle information on CPU cpuid */
    1.46 +static int show_cx_cpuid(int xc_fd, int cpuid)
    1.47  {
    1.48 -    int xc_fd;
    1.49 -    int i, j, ret = 0;
    1.50 -    int cinfo = 0, pinfo = 0;
    1.51 -    int ch;
    1.52 +    int i, ret = 0;
    1.53 +    int max_cx_num = 0;
    1.54 +    struct xc_cx_stat cxstatinfo, *cxstat = &cxstatinfo;
    1.55 +
    1.56 +    ret = xc_pm_get_max_cx(xc_fd, cpuid, &max_cx_num);
    1.57 +    if ( ret )
    1.58 +    {
    1.59 +        if ( errno == ENODEV )
    1.60 +        {
    1.61 +            fprintf(stderr, "Xen cpuidle is not enabled!\n");
    1.62 +            return -ENODEV;
    1.63 +        }
    1.64 +        else
    1.65 +        {
    1.66 +            fprintf(stderr, "[CPU%d] failed to get max C-state\n", cpuid);
    1.67 +            return -EINVAL;
    1.68 +        }
    1.69 +    }
    1.70 +
    1.71 +    cxstat->triggers = malloc(max_cx_num * sizeof(uint64_t));
    1.72 +    if ( !cxstat->triggers )
    1.73 +    {
    1.74 +        fprintf(stderr, "[CPU%d] failed to malloc for C-states triggers\n", cpuid);
    1.75 +        return -ENOMEM;
    1.76 +    }
    1.77 +    cxstat->residencies = malloc(max_cx_num * sizeof(uint64_t));
    1.78 +    if ( !cxstat->residencies )
    1.79 +    {
    1.80 +        fprintf(stderr, "[CPU%d] failed to malloc for C-states residencies\n", cpuid);
    1.81 +        free(cxstat->triggers);
    1.82 +        return -ENOMEM;
    1.83 +    }
    1.84 +
    1.85 +    ret = xc_pm_get_cxstat(xc_fd, cpuid, cxstat);
    1.86 +    if( ret )
    1.87 +    {
    1.88 +        fprintf(stderr, "[CPU%d] failed to get C-states statistics "
    1.89 +                "information\n", cpuid);
    1.90 +        free(cxstat->triggers);
    1.91 +        free(cxstat->residencies);
    1.92 +        return -EINVAL;
    1.93 +    }
    1.94 +
    1.95 +    printf("cpu id               : %d\n", cpuid);
    1.96 +    printf("total C-states       : %d\n", cxstat->nr);
    1.97 +    printf("idle time(ms)        : %"PRIu64"\n",
    1.98 +           cxstat->idle_time/1000000UL);
    1.99 +    for ( i = 0; i < cxstat->nr; i++ )
   1.100 +    {
   1.101 +        printf("C%d                   : transition [%020"PRIu64"]\n",
   1.102 +               i, cxstat->triggers[i]);
   1.103 +        printf("                       residency  [%020"PRIu64" ms]\n",
   1.104 +               cxstat->residencies[i]*1000000UL/3579/1000000UL);
   1.105 +    }
   1.106 +
   1.107 +    free(cxstat->triggers);
   1.108 +    free(cxstat->residencies);
   1.109 +
   1.110 +    printf("\n");
   1.111 +    return 0;
   1.112 +}
   1.113 +
   1.114 +int cxstates_func(int xc_fd, int cpuid, uint32_t value)
   1.115 +{
   1.116 +    int ret = 0;
   1.117      xc_physinfo_t physinfo = { 0 };
   1.118  
   1.119 -    while ( (ch = getopt(argc, argv, "cp")) != -1 )
   1.120 +    if ( cpuid < 0 )
   1.121      {
   1.122 -        switch ( ch )
   1.123 +        /* show cxstates on all cpu */
   1.124 +        ret = xc_physinfo(xc_fd, &physinfo);
   1.125 +        if ( ret )
   1.126 +        {
   1.127 +            fprintf(stderr, "failed to get the processor information\n");
   1.128 +        }
   1.129 +        else
   1.130          {
   1.131 -        case 'c':
   1.132 -            cinfo = 1;
   1.133 -            break;
   1.134 -        case 'p':
   1.135 -            pinfo = 1;
   1.136 -            break;
   1.137 -        default:
   1.138 -            fprintf(stderr, "%s [-p] [-c]\n", argv[0]);
   1.139 -            return -1;
   1.140 +            int i;
   1.141 +            for ( i = 0; i < physinfo.nr_cpus; i++ )
   1.142 +            {
   1.143 +                if ( (ret = show_cx_cpuid(xc_fd, i)) == -ENODEV )
   1.144 +                    break;
   1.145 +            }
   1.146 +        }
   1.147 +    }
   1.148 +    else
   1.149 +        ret = show_cx_cpuid(xc_fd, cpuid);
   1.150 +
   1.151 +    return ret;
   1.152 +}
   1.153 +
   1.154 +/* show cpu frequency information on CPU cpuid */
   1.155 +static int show_px_cpuid(int xc_fd, int cpuid)
   1.156 +{
   1.157 +    int i, ret = 0;
   1.158 +    int max_px_num = 0;
   1.159 +    struct xc_px_stat pxstatinfo, *pxstat = &pxstatinfo;
   1.160 +
   1.161 +    ret = xc_pm_get_max_px(xc_fd, cpuid, &max_px_num);
   1.162 +    if ( ret )
   1.163 +    {
   1.164 +        if ( errno == ENODEV )
   1.165 +        {
   1.166 +            printf("Xen cpufreq is not enabled!\n");
   1.167 +            return -ENODEV;
   1.168 +        }
   1.169 +        else
   1.170 +        {
   1.171 +            fprintf(stderr, "[CPU%d] failed to get max P-state\n", cpuid);
   1.172 +            return -EINVAL;
   1.173          }
   1.174      }
   1.175  
   1.176 -    if ( !cinfo && !pinfo )
   1.177 +    pxstat->trans_pt = malloc(max_px_num * max_px_num *
   1.178 +                              sizeof(uint64_t));
   1.179 +    if ( !pxstat->trans_pt )
   1.180 +    {
   1.181 +        fprintf(stderr, "[CPU%d] failed to malloc for P-states transition table\n", cpuid);
   1.182 +        return -ENOMEM;
   1.183 +    }
   1.184 +    pxstat->pt = malloc(max_px_num * sizeof(struct xc_px_val));
   1.185 +    if ( !pxstat->pt )
   1.186 +    {
   1.187 +        fprintf(stderr, "[CPU%d] failed to malloc for P-states table\n", cpuid);
   1.188 +        free(pxstat->trans_pt);
   1.189 +        return -ENOMEM;
   1.190 +    }
   1.191 +
   1.192 +    ret = xc_pm_get_pxstat(xc_fd, cpuid, pxstat);
   1.193 +    if( ret )
   1.194 +    {
   1.195 +        fprintf(stderr, "[CPU%d] failed to get P-states statistics information\n", cpuid);
   1.196 +        free(pxstat->trans_pt);
   1.197 +        free(pxstat->pt);
   1.198 +        return -ENOMEM;
   1.199 +    }
   1.200 +
   1.201 +    printf("cpu id               : %d\n", cpuid);
   1.202 +    printf("total P-states       : %d\n", pxstat->total);
   1.203 +    printf("usable P-states      : %d\n", pxstat->usable);
   1.204 +    printf("current frequency    : %"PRIu64" MHz\n",
   1.205 +           pxstat->pt[pxstat->cur].freq);
   1.206 +    for ( i = 0; i < pxstat->total; i++ )
   1.207 +    {
   1.208 +        if ( pxstat->cur == i )
   1.209 +            printf("*P%d", i);
   1.210 +        else
   1.211 +            printf("P%d ", i);
   1.212 +        printf("                  : freq       [%04"PRIu64" MHz]\n",
   1.213 +               pxstat->pt[i].freq);
   1.214 +        printf("                       transition [%020"PRIu64"]\n",
   1.215 +               pxstat->pt[i].count);
   1.216 +        printf("                       residency  [%020"PRIu64" ms]\n",
   1.217 +               pxstat->pt[i].residency/1000000UL);
   1.218 +    }
   1.219 +
   1.220 +    free(pxstat->trans_pt);
   1.221 +    free(pxstat->pt);
   1.222 +
   1.223 +    printf("\n");
   1.224 +    return 0;
   1.225 +}
   1.226 +
   1.227 +int pxstates_func(int xc_fd, int cpuid, uint32_t value)
   1.228 +{
   1.229 +    int ret = 0;
   1.230 +    xc_physinfo_t physinfo = { 0 };
   1.231 +
   1.232 +    if ( cpuid < 0 )
   1.233 +    {
   1.234 +        ret = xc_physinfo(xc_fd, &physinfo);
   1.235 +        if ( ret )
   1.236 +        {
   1.237 +            fprintf(stderr, "failed to get the processor information\n");
   1.238 +        }
   1.239 +        else
   1.240 +        {
   1.241 +            int i;
   1.242 +            for ( i = 0; i < physinfo.nr_cpus; i++ )
   1.243 +            {
   1.244 +                if ( (ret = show_px_cpuid(xc_fd, i)) == -ENODEV )
   1.245 +                    break;
   1.246 +            }
   1.247 +        }
   1.248 +    }
   1.249 +    else
   1.250 +        ret = show_px_cpuid(xc_fd, cpuid);
   1.251 +
   1.252 +    return ret;
   1.253 +}
   1.254 +
   1.255 +/* print out parameters about cpu frequency */
   1.256 +static void print_cpufreq_para(int cpuid, struct xc_get_cpufreq_para *p_cpufreq)
   1.257 +{
   1.258 +    int i;
   1.259 +
   1.260 +    printf("cpu id               : %d\n", cpuid);
   1.261 +
   1.262 +    printf("affected_cpus        :");
   1.263 +    for ( i = 0; i < p_cpufreq->cpu_num; i++ )
   1.264 +        if ( i == cpuid )
   1.265 +            printf(" *%d", p_cpufreq->affected_cpus[i]);
   1.266 +        else
   1.267 +            printf(" %d", p_cpufreq->affected_cpus[i]);
   1.268 +    printf("\n");
   1.269 +
   1.270 +    printf("cpuinfo frequency    : max [%u] min [%u] cur [%u]\n",
   1.271 +           p_cpufreq->cpuinfo_max_freq,
   1.272 +           p_cpufreq->cpuinfo_min_freq,
   1.273 +           p_cpufreq->cpuinfo_cur_freq);
   1.274 +
   1.275 +    printf("scaling_driver       : %s\n", p_cpufreq->scaling_driver);
   1.276 +
   1.277 +    printf("scaling_avail_gov    : %s\n",
   1.278 +           p_cpufreq->scaling_available_governors);
   1.279 +
   1.280 +    printf("current_governor     : %s\n", p_cpufreq->scaling_governor);
   1.281 +    if ( !strncmp(p_cpufreq->scaling_governor,
   1.282 +                  "userspace", CPUFREQ_NAME_LEN) )
   1.283 +    {
   1.284 +        printf("  userspace specific :\n");
   1.285 +        printf("    scaling_setspeed : %u\n",
   1.286 +               p_cpufreq->u.userspace.scaling_setspeed);
   1.287 +    }
   1.288 +    else if ( !strncmp(p_cpufreq->scaling_governor,
   1.289 +                       "ondemand", CPUFREQ_NAME_LEN) )
   1.290 +    {
   1.291 +        printf("  ondemand specific  :\n");
   1.292 +        printf("    sampling_rate    : max [%u] min [%u] cur [%u]\n",
   1.293 +               p_cpufreq->u.ondemand.sampling_rate_max,
   1.294 +               p_cpufreq->u.ondemand.sampling_rate_min,
   1.295 +               p_cpufreq->u.ondemand.sampling_rate);
   1.296 +        printf("    up_threshold     : %u\n",
   1.297 +               p_cpufreq->u.ondemand.up_threshold);
   1.298 +    }
   1.299 +
   1.300 +    printf("scaling_avail_freq   :");
   1.301 +    for ( i = 0; i < p_cpufreq->freq_num; i++ )
   1.302 +        if ( p_cpufreq->scaling_available_frequencies[i] == p_cpufreq->scaling_cur_freq )
   1.303 +            printf(" *%d", p_cpufreq->scaling_available_frequencies[i]);
   1.304 +        else
   1.305 +            printf(" %d", p_cpufreq->scaling_available_frequencies[i]);
   1.306 +    printf("\n");
   1.307 +
   1.308 +    printf("scaling frequency    : max [%u] min [%u] cur [%u]\n",
   1.309 +           p_cpufreq->scaling_max_freq,
   1.310 +           p_cpufreq->scaling_min_freq,
   1.311 +           p_cpufreq->scaling_cur_freq);
   1.312 +    printf("\n");
   1.313 +}
   1.314 +
   1.315 +/* show cpu frequency parameters information on CPU cpuid */
   1.316 +static int show_cpufreq_para_cpuid(int xc_fd, int cpuid)
   1.317 +{
   1.318 +    int ret = 0;
   1.319 +    struct xc_get_cpufreq_para cpufreq_para, *p_cpufreq = &cpufreq_para;
   1.320 +
   1.321 +    p_cpufreq->cpu_num = 0;
   1.322 +    p_cpufreq->freq_num = 0;
   1.323 +    p_cpufreq->gov_num = 0;
   1.324 +    p_cpufreq->affected_cpus = NULL;
   1.325 +    p_cpufreq->scaling_available_frequencies = NULL;
   1.326 +    p_cpufreq->scaling_available_governors = NULL;
   1.327 +
   1.328 +    do
   1.329      {
   1.330 -        cinfo = 1;
   1.331 -        pinfo = 1;
   1.332 +        free(p_cpufreq->affected_cpus);
   1.333 +        free(p_cpufreq->scaling_available_frequencies);
   1.334 +        free(p_cpufreq->scaling_available_governors);
   1.335 +
   1.336 +        p_cpufreq->affected_cpus = NULL;
   1.337 +        p_cpufreq->scaling_available_frequencies = NULL;
   1.338 +        p_cpufreq->scaling_available_governors = NULL;
   1.339 +
   1.340 +        if (!(p_cpufreq->affected_cpus =
   1.341 +              malloc(p_cpufreq->cpu_num * sizeof(uint32_t))))
   1.342 +        {
   1.343 +            fprintf(stderr,
   1.344 +                    "[CPU%d] failed to malloc for affected_cpus\n",
   1.345 +                    cpuid);
   1.346 +            ret = -ENOMEM;
   1.347 +            goto out;
   1.348 +        }
   1.349 +        if (!(p_cpufreq->scaling_available_frequencies =
   1.350 +              malloc(p_cpufreq->freq_num * sizeof(uint32_t))))
   1.351 +        {
   1.352 +            fprintf(stderr,
   1.353 +                    "[CPU%d] failed to malloc for scaling_available_frequencies\n",
   1.354 +                    cpuid);
   1.355 +            ret = -ENOMEM;
   1.356 +            goto out;
   1.357 +        }
   1.358 +        if (!(p_cpufreq->scaling_available_governors =
   1.359 +              malloc(p_cpufreq->gov_num * CPUFREQ_NAME_LEN * sizeof(char))))
   1.360 +        {
   1.361 +            fprintf(stderr,
   1.362 +                    "[CPU%d] failed to malloc for scaling_available_governors\n",
   1.363 +                    cpuid);
   1.364 +            ret = -ENOMEM;
   1.365 +            goto out;
   1.366 +        }
   1.367 +
   1.368 +        ret = xc_get_cpufreq_para(xc_fd, cpuid, p_cpufreq);
   1.369 +    } while ( ret && errno == EAGAIN );
   1.370 +
   1.371 +    if ( ret == 0 )
   1.372 +        print_cpufreq_para(cpuid, p_cpufreq);
   1.373 +    else if ( errno == ENODEV )
   1.374 +    {
   1.375 +        ret = -ENODEV;
   1.376 +        fprintf(stderr, "Xen cpufreq is not enabled!\n");
   1.377 +    }
   1.378 +    else
   1.379 +        fprintf(stderr,
   1.380 +                "[CPU%d] failed to get cpufreq parameter\n",
   1.381 +                cpuid);
   1.382 +
   1.383 +out:
   1.384 +    free(p_cpufreq->scaling_available_governors);
   1.385 +    free(p_cpufreq->scaling_available_frequencies);
   1.386 +    free(p_cpufreq->affected_cpus);
   1.387 +
   1.388 +    return ret;
   1.389 +}
   1.390 +
   1.391 +int cpufreq_para_func(int xc_fd, int cpuid, uint32_t value)
   1.392 +{
   1.393 +    int ret = 0;
   1.394 +    xc_physinfo_t physinfo = { 0 };
   1.395 +
   1.396 +    if ( cpuid < 0 )
   1.397 +    {
   1.398 +        ret = xc_physinfo(xc_fd, &physinfo);
   1.399 +        if ( ret )
   1.400 +        {
   1.401 +            fprintf(stderr, "failed to get the processor information\n");
   1.402 +        }
   1.403 +        else
   1.404 +        {
   1.405 +            int i;
   1.406 +            for ( i = 0; i < physinfo.nr_cpus; i++ )
   1.407 +            {
   1.408 +                if ( (ret = show_cpufreq_para_cpuid(xc_fd, i)) == -ENODEV )
   1.409 +                    break;
   1.410 +            }
   1.411 +        }
   1.412 +    }
   1.413 +    else
   1.414 +        ret = show_cpufreq_para_cpuid(xc_fd, cpuid);
   1.415 +
   1.416 +    return ret;
   1.417 +}
   1.418 +
   1.419 +int scaling_max_freq_func(int xc_fd, int cpuid, uint32_t value)
   1.420 +{
   1.421 +    int ret = 0;
   1.422 +
   1.423 +    if ( cpuid < 0 )
   1.424 +    {
   1.425 +        show_help();
   1.426 +        return -EINVAL;
   1.427 +    }
   1.428 +
   1.429 +    ret = xc_set_cpufreq_para(xc_fd, cpuid, SCALING_MAX_FREQ, value);
   1.430 +    if ( ret )
   1.431 +    {
   1.432 +        fprintf(stderr, "[CPU%d] failed to set scaling max freq\n", cpuid);
   1.433 +    }
   1.434 +
   1.435 +    return ret;
   1.436 +}
   1.437 +
   1.438 +int scaling_min_freq_func(int xc_fd, int cpuid, uint32_t value)
   1.439 +{
   1.440 +    int ret;
   1.441 +
   1.442 +    if ( cpuid < 0 )
   1.443 +    {
   1.444 +        show_help();
   1.445 +        return -EINVAL;
   1.446 +    }
   1.447 +
   1.448 +    ret = xc_set_cpufreq_para(xc_fd, cpuid, SCALING_MIN_FREQ, value);
   1.449 +    if ( ret )
   1.450 +    {
   1.451 +        fprintf(stderr, "[CPU%d] failed to set scaling min freq\n", cpuid);
   1.452 +    }
   1.453 +
   1.454 +    return ret;
   1.455 +}
   1.456 +
   1.457 +int scaling_speed_func(int xc_fd, int cpuid, uint32_t value)
   1.458 +{
   1.459 +    int ret;
   1.460 +
   1.461 +    if ( cpuid < 0 )
   1.462 +    {
   1.463 +        show_help();
   1.464 +        return -EINVAL;
   1.465 +    }
   1.466 +
   1.467 +    ret = xc_set_cpufreq_para(xc_fd, cpuid, SCALING_SETSPEED, value);
   1.468 +    if ( ret )
   1.469 +    {
   1.470 +        fprintf(stderr, "[CPU%d] failed to set scaling speed\n", cpuid);
   1.471 +    }
   1.472 +
   1.473 +    return ret;
   1.474 +}
   1.475 +
   1.476 +int scaling_sampling_rate_func(int xc_fd, int cpuid, uint32_t value)
   1.477 +{
   1.478 +    int ret;
   1.479 +
   1.480 +    if ( cpuid < 0 )
   1.481 +    {
   1.482 +        show_help();
   1.483 +        return -EINVAL;
   1.484 +    }
   1.485 +
   1.486 +    ret = xc_set_cpufreq_para(xc_fd, cpuid, SAMPLING_RATE, value);
   1.487 +    if ( ret ) 
   1.488 +    {
   1.489 +        fprintf(stderr, "[CPU%d] failed to set scaling sampling rate\n", cpuid);
   1.490 +    }
   1.491 +
   1.492 +    return ret;
   1.493 +}
   1.494 +
   1.495 +int scaling_up_threshold_func(int xc_fd, int cpuid, uint32_t value)
   1.496 +{
   1.497 +    int ret;
   1.498 +
   1.499 +    if ( cpuid < 0 )
   1.500 +    {
   1.501 +        show_help();
   1.502 +        return -EINVAL;
   1.503 +    }
   1.504 +
   1.505 +    ret = xc_set_cpufreq_para(xc_fd, cpuid, UP_THRESHOLD, value);
   1.506 +    if ( ret )
   1.507 +    {
   1.508 +        fprintf(stderr, "[CPU%d] failed to set scaling threshold\n", cpuid);
   1.509 +    }
   1.510 +
   1.511 +    return ret;
   1.512 +}
   1.513 +
   1.514 +int scaling_governor_func(int xc_fd, int cpuid, char *name)
   1.515 +{
   1.516 +    int ret = 0;
   1.517 +
   1.518 +    if ( cpuid < 0 )
   1.519 +    {
   1.520 +        show_help();
   1.521 +        return -EINVAL;
   1.522 +    }
   1.523 +
   1.524 +    ret = xc_set_cpufreq_gov(xc_fd, cpuid, name);
   1.525 +    if ( ret )
   1.526 +    {
   1.527 +        fprintf(stderr, "failed to set cpufreq governor to %s\n", name);
   1.528 +    }
   1.529 +
   1.530 +    return ret;
   1.531 +}
   1.532 +
   1.533 +struct {
   1.534 +    const char *name;
   1.535 +    int (*function)(int xc_fd, int cpuid, uint32_t value);
   1.536 +} main_options[] = {
   1.537 +    { "help", help_func },
   1.538 +    { "get-cpuidle-states", cxstates_func },
   1.539 +    { "get-cpufreq-states", pxstates_func },
   1.540 +    { "get-cpufreq-para", cpufreq_para_func },
   1.541 +    { "set-scaling-maxfreq", scaling_max_freq_func },
   1.542 +    { "set-scaling-minfreq", scaling_min_freq_func },
   1.543 +    { "set-scaling-governor", NULL },
   1.544 +    { "set-scaling-speed", scaling_speed_func },
   1.545 +    { "set-sampling-rate", scaling_sampling_rate_func },
   1.546 +    { "set-up-threshold", scaling_up_threshold_func },
   1.547 +};
   1.548 +
   1.549 +int main(int argc, char *argv[])
   1.550 +{
   1.551 +    int i, ret = -EINVAL;
   1.552 +    int xc_fd;
   1.553 +    int cpuid = -1;
   1.554 +    uint32_t value = 0;
   1.555 +    int nr_matches = 0;
   1.556 +    int matches_main_options[ARRAY_SIZE(main_options)];
   1.557 +
   1.558 +    if ( argc < 2 )
   1.559 +    {
   1.560 +        show_help();
   1.561 +        return ret;
   1.562 +    }
   1.563 +
   1.564 +    if ( argc > 2 )
   1.565 +    {
   1.566 +        if ( sscanf(argv[2], "%d", &cpuid) != 1 )
   1.567 +            cpuid = -1;
   1.568      }
   1.569  
   1.570      xc_fd = xc_interface_open();
   1.571      if ( xc_fd < 0 )
   1.572      {
   1.573          fprintf(stderr, "failed to get the handler\n");
   1.574 -        return xc_fd;
   1.575 -    }
   1.576 -
   1.577 -    ret = xc_physinfo(xc_fd, &physinfo);
   1.578 -    if ( ret )
   1.579 -    {
   1.580 -        fprintf(stderr, "failed to get the processor information\n");
   1.581 -        xc_interface_close(xc_fd);
   1.582 -        return ret;
   1.583      }
   1.584  
   1.585 -    /* print out the C state information */
   1.586 -    if ( cinfo )
   1.587 +    for ( i = 0; i < ARRAY_SIZE(main_options); i++ )
   1.588      {
   1.589 -        int max_cx_num = 0;
   1.590 -        struct xc_cx_stat cxstatinfo, *cxstat = &cxstatinfo;
   1.591 -
   1.592 -        for ( i = 0; i < physinfo.nr_cpus; i++ )
   1.593 +        if ( !strncmp(main_options[i].name, argv[1], strlen(argv[1])) )
   1.594          {
   1.595 -            ret = xc_pm_get_max_cx(xc_fd, i, &max_cx_num);
   1.596 -            if ( ret )
   1.597 -            {
   1.598 -                if ( errno == ENODEV )
   1.599 -                {
   1.600 -                    fprintf(stderr, "Xen cpuidle is not enabled!\n");
   1.601 -                    break;
   1.602 -                }
   1.603 -                else
   1.604 -                {
   1.605 -                    fprintf(stderr, "[CPU%d] failed to get max C-state\n", i);
   1.606 -                    continue;
   1.607 -                }
   1.608 -            }
   1.609 -
   1.610 -            cxstat->triggers = malloc(max_cx_num * sizeof(uint64_t));
   1.611 -            if ( !cxstat->triggers )
   1.612 -            {
   1.613 -                fprintf(stderr, "failed to malloc for C-states triggers\n");
   1.614 -                break;
   1.615 -            }
   1.616 -            cxstat->residencies = malloc(max_cx_num * sizeof(uint64_t));
   1.617 -            if ( !cxstat->residencies )
   1.618 -            {
   1.619 -                fprintf(stderr, "failed to malloc for C-states residencies\n");
   1.620 -                free(cxstat->triggers);
   1.621 -                break;
   1.622 -            }
   1.623 -
   1.624 -            ret = xc_pm_get_cxstat(xc_fd, i, cxstat);
   1.625 -            if( ret )
   1.626 -            {
   1.627 -                fprintf(stderr, "[CPU%d] failed to get C-states statistics "
   1.628 -                        "information\n", i);
   1.629 -                free(cxstat->triggers);
   1.630 -                free(cxstat->residencies);
   1.631 -                continue;
   1.632 -            }
   1.633 -
   1.634 -            printf("cpu id               : %d\n", i);
   1.635 -            printf("total C-states       : %d\n", cxstat->nr);
   1.636 -            printf("idle time(ms)        : %"PRIu64"\n",
   1.637 -                   cxstat->idle_time/1000000UL);
   1.638 -            for ( j = 0; j < cxstat->nr; j++ )
   1.639 -            {
   1.640 -                printf("C%d                   : transition [%020"PRIu64"]\n",
   1.641 -                       j, cxstat->triggers[j]);
   1.642 -                printf("                       residency  [%020"PRIu64" ms]\n",
   1.643 -                       cxstat->residencies[j]*1000000UL/3579/1000000UL);
   1.644 -            }
   1.645 -
   1.646 -            free(cxstat->triggers);
   1.647 -            free(cxstat->residencies);
   1.648 -
   1.649 -            printf("\n");
   1.650 +            matches_main_options[nr_matches++] = i;
   1.651          }
   1.652      }
   1.653  
   1.654 -    /* print out P state information */
   1.655 -    if ( pinfo )
   1.656 +    if ( nr_matches > 1 )
   1.657      {
   1.658 -        int max_px_num = 0;
   1.659 -        struct xc_px_stat pxstatinfo, *pxstat = &pxstatinfo;
   1.660 -
   1.661 -        for ( i = 0; i < physinfo.nr_cpus; i++ )
   1.662 +        fprintf(stderr, "Ambigious options: ");
   1.663 +        for ( i = 0; i < nr_matches; i++ )
   1.664 +            fprintf(stderr, " %s", main_options[matches_main_options[i]].name);
   1.665 +        fprintf(stderr, "\n");
   1.666 +    }
   1.667 +    else if ( nr_matches == 1 )
   1.668 +    {
   1.669 +        if ( !strcmp("set-scaling-governor", main_options[matches_main_options[0]].name) )
   1.670          {
   1.671 -            ret = xc_pm_get_max_px(xc_fd, i, &max_px_num);
   1.672 -            if ( ret )
   1.673 -            {
   1.674 -                if ( errno == ENODEV )
   1.675 -                {
   1.676 -                    printf("Xen cpufreq is not enabled!\n");
   1.677 -                    break;
   1.678 -                }
   1.679 -                else
   1.680 -                {
   1.681 -                    fprintf(stderr, "[CPU%d] failed to get max P-state\n", i);
   1.682 -                    continue;
   1.683 -                }
   1.684 -            }
   1.685 -
   1.686 -            pxstat->trans_pt = malloc(max_px_num * max_px_num *
   1.687 -                                      sizeof(uint64_t));
   1.688 -            if ( !pxstat->trans_pt )
   1.689 -            {
   1.690 -                fprintf(stderr, "failed to malloc for P-states "
   1.691 -                        "transition table\n");
   1.692 -                break;
   1.693 -            }
   1.694 -            pxstat->pt = malloc(max_px_num * sizeof(struct xc_px_val));
   1.695 -            if ( !pxstat->pt )
   1.696 +            char *name = strdup(argv[3]);
   1.697 +            ret = scaling_governor_func(xc_fd, cpuid, name);
   1.698 +            free(name);
   1.699 +        }
   1.700 +        else
   1.701 +        {
   1.702 +            if ( argc > 3 )
   1.703              {
   1.704 -                fprintf(stderr, "failed to malloc for P-states table\n");
   1.705 -                free(pxstat->trans_pt);
   1.706 -                break;
   1.707 -            }
   1.708 -
   1.709 -            ret = xc_pm_get_pxstat(xc_fd, i, pxstat);
   1.710 -            if( ret )
   1.711 -            {
   1.712 -                fprintf(stderr, "[CPU%d] failed to get P-states "
   1.713 -                        "statistics information\n", i);
   1.714 -                free(pxstat->trans_pt);
   1.715 -                free(pxstat->pt);
   1.716 -                continue;
   1.717 +                if ( sscanf(argv[3], "%d", &value) != 1 )
   1.718 +                    value = 0;
   1.719              }
   1.720 -
   1.721 -            printf("cpu id               : %d\n", i);
   1.722 -            printf("total P-states       : %d\n", pxstat->total);
   1.723 -            printf("usable P-states      : %d\n", pxstat->usable);
   1.724 -            printf("current frequency    : %"PRIu64" MHz\n",
   1.725 -                   pxstat->pt[pxstat->cur].freq);
   1.726 -            for ( j = 0; j < pxstat->total; j++ )
   1.727 -            {
   1.728 -                if ( pxstat->cur == j )
   1.729 -                    printf("*P%d", j);
   1.730 -                else
   1.731 -                    printf("P%d ", j);
   1.732 -                printf("                  : freq       [%04"PRIu64" MHz]\n",
   1.733 -                       pxstat->pt[j].freq);
   1.734 -                printf("                       transition [%020"PRIu64"]\n",
   1.735 -                       pxstat->pt[j].count);
   1.736 -                printf("                       residency  [%020"PRIu64" ms]\n",
   1.737 -                       pxstat->pt[j].residency/1000000UL);
   1.738 -            }
   1.739 -
   1.740 -            free(pxstat->trans_pt);
   1.741 -            free(pxstat->pt);
   1.742 -
   1.743 -            printf("\n");
   1.744 +            ret = main_options[matches_main_options[0]].function(xc_fd, cpuid, value);
   1.745          }
   1.746      }
   1.747 +    else
   1.748 +        show_help();
   1.749  
   1.750      xc_interface_close(xc_fd);
   1.751      return ret;