ia64/xen-unstable

changeset 18904:605ef79ee46c

Add user PM control interface

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Dec 10 13:27:41 2008 +0000 (2008-12-10)
parents 9ba1541d6dc2
children 265baac90802
files tools/libxc/xc_pm.c tools/libxc/xenctrl.h xen/arch/ia64/xen/cpufreq/cpufreq.c xen/arch/x86/acpi/cpufreq/cpufreq.c xen/common/sysctl.c xen/drivers/acpi/pmstat.c xen/drivers/cpufreq/cpufreq.c xen/drivers/cpufreq/cpufreq_ondemand.c xen/include/acpi/cpufreq/cpufreq.h xen/include/public/sysctl.h
line diff
     1.1 --- a/tools/libxc/xc_pm.c	Wed Dec 10 13:27:14 2008 +0000
     1.2 +++ b/tools/libxc/xc_pm.c	Wed Dec 10 13:27:41 2008 +0000
     1.3 @@ -23,8 +23,15 @@
     1.4   *
     1.5   */
     1.6  
     1.7 +#include <errno.h>
     1.8 +#include <curses.h>
     1.9 +#include <linux/kernel.h>
    1.10 +
    1.11  #include "xc_private.h"
    1.12  
    1.13 +/*
    1.14 + * Get PM statistic info
    1.15 + */
    1.16  int xc_pm_get_max_px(int xc_handle, int cpuid, int *max_px)
    1.17  {
    1.18      DECLARE_SYSCTL;
    1.19 @@ -168,3 +175,136 @@ int xc_pm_reset_cxstat(int xc_handle, in
    1.20  
    1.21      return xc_sysctl(xc_handle, &sysctl);
    1.22  }
    1.23 +
    1.24 +
    1.25 +/*
    1.26 + * 1. Get PM parameter
    1.27 + * 2. Provide user PM control
    1.28 + */
    1.29 +int xc_get_cpufreq_para(int xc_handle, int cpuid,
    1.30 +                        struct xc_get_cpufreq_para *user_para)
    1.31 +{
    1.32 +    DECLARE_SYSCTL;
    1.33 +    int ret = 0;
    1.34 +    struct xen_get_cpufreq_para *sys_para = &sysctl.u.pm_op.get_para;
    1.35 +    bool has_num = user_para->cpu_num &&
    1.36 +                     user_para->freq_num &&
    1.37 +                     user_para->gov_num;
    1.38 +
    1.39 +    if ( (xc_handle < 0) || !user_para )
    1.40 +        return -EINVAL;
    1.41 +
    1.42 +    if ( has_num )
    1.43 +    {
    1.44 +        if ( (!user_para->affected_cpus)                    ||
    1.45 +             (!user_para->scaling_available_frequencies)    ||
    1.46 +             (!user_para->scaling_available_governors) )
    1.47 +            return -EINVAL;
    1.48 +
    1.49 +        if ( (ret = lock_pages(user_para->affected_cpus,
    1.50 +                               user_para->cpu_num * sizeof(uint32_t))) )
    1.51 +            goto unlock_1;
    1.52 +        if ( (ret = lock_pages(user_para->scaling_available_frequencies,
    1.53 +                               user_para->freq_num * sizeof(uint32_t))) )
    1.54 +            goto unlock_2;
    1.55 +        if ( (ret = lock_pages(user_para->scaling_available_governors,
    1.56 +                 user_para->gov_num * CPUFREQ_NAME_LEN * sizeof(char))) )
    1.57 +            goto unlock_3;
    1.58 +
    1.59 +        set_xen_guest_handle(sys_para->affected_cpus,
    1.60 +                             user_para->affected_cpus);
    1.61 +        set_xen_guest_handle(sys_para->scaling_available_frequencies,
    1.62 +                             user_para->scaling_available_frequencies);
    1.63 +        set_xen_guest_handle(sys_para->scaling_available_governors,
    1.64 +                             user_para->scaling_available_governors);
    1.65 +    }
    1.66 +
    1.67 +    sysctl.cmd = XEN_SYSCTL_pm_op;
    1.68 +    sysctl.u.pm_op.cmd = GET_CPUFREQ_PARA;
    1.69 +    sysctl.u.pm_op.cpuid = cpuid;
    1.70 +    sys_para->cpu_num  = user_para->cpu_num;
    1.71 +    sys_para->freq_num = user_para->freq_num;
    1.72 +    sys_para->gov_num  = user_para->gov_num;
    1.73 +
    1.74 +    ret = xc_sysctl(xc_handle, &sysctl);
    1.75 +    if ( ret )
    1.76 +    {
    1.77 +        if ( errno == EAGAIN )
    1.78 +        {
    1.79 +            user_para->cpu_num  = sys_para->cpu_num;
    1.80 +            user_para->freq_num = sys_para->freq_num;
    1.81 +            user_para->gov_num  = sys_para->gov_num;
    1.82 +            ret = -errno;
    1.83 +        }
    1.84 +
    1.85 +        if ( has_num )
    1.86 +            goto unlock_4;
    1.87 +        goto unlock_1;
    1.88 +    }
    1.89 +    else
    1.90 +    {
    1.91 +        user_para->cpuinfo_cur_freq = sys_para->cpuinfo_cur_freq;
    1.92 +        user_para->cpuinfo_max_freq = sys_para->cpuinfo_max_freq;
    1.93 +        user_para->cpuinfo_min_freq = sys_para->cpuinfo_min_freq;
    1.94 +        user_para->scaling_cur_freq = sys_para->scaling_cur_freq;
    1.95 +        user_para->scaling_max_freq = sys_para->scaling_max_freq;
    1.96 +        user_para->scaling_min_freq = sys_para->scaling_min_freq;
    1.97 +
    1.98 +        memcpy(user_para->scaling_driver, 
    1.99 +                sys_para->scaling_driver, CPUFREQ_NAME_LEN);
   1.100 +        memcpy(user_para->scaling_governor,
   1.101 +                sys_para->scaling_governor, CPUFREQ_NAME_LEN);
   1.102 +
   1.103 +        /* copy to user_para no matter what cpufreq governor */
   1.104 +        BUILD_BUG_ON(sizeof(((struct xc_get_cpufreq_para *)0)->u) !=
   1.105 +                     sizeof(((struct xen_get_cpufreq_para *)0)->u));
   1.106 +
   1.107 +        memcpy(&user_para->u, &sys_para->u, sizeof(sys_para->u));
   1.108 +    }
   1.109 +
   1.110 +unlock_4:
   1.111 +    unlock_pages(user_para->scaling_available_governors,
   1.112 +                 user_para->gov_num * CPUFREQ_NAME_LEN * sizeof(char));
   1.113 +unlock_3:
   1.114 +    unlock_pages(user_para->scaling_available_frequencies,
   1.115 +                 user_para->freq_num * sizeof(uint32_t));
   1.116 +unlock_2:
   1.117 +    unlock_pages(user_para->affected_cpus,
   1.118 +                 user_para->cpu_num * sizeof(uint32_t));
   1.119 +unlock_1:
   1.120 +    return ret;
   1.121 +}
   1.122 +
   1.123 +int xc_set_cpufreq_gov(int xc_handle, int cpuid, char *govname)
   1.124 +{
   1.125 +    DECLARE_SYSCTL;
   1.126 +    char *scaling_governor = sysctl.u.pm_op.set_gov.scaling_governor;
   1.127 +
   1.128 +    if ( (xc_handle < 0) || (!govname) )
   1.129 +        return -EINVAL;
   1.130 +
   1.131 +    sysctl.cmd = XEN_SYSCTL_pm_op;
   1.132 +    sysctl.u.pm_op.cmd = SET_CPUFREQ_GOV;
   1.133 +    sysctl.u.pm_op.cpuid = cpuid;
   1.134 +    strncpy(scaling_governor, govname, CPUFREQ_NAME_LEN);
   1.135 +    scaling_governor[CPUFREQ_NAME_LEN] = '\0';
   1.136 +
   1.137 +    return xc_sysctl(xc_handle, &sysctl);
   1.138 +}
   1.139 +
   1.140 +int xc_set_cpufreq_para(int xc_handle, int cpuid, 
   1.141 +                        int ctrl_type, int ctrl_value)
   1.142 +{
   1.143 +    DECLARE_SYSCTL;
   1.144 +
   1.145 +    if ( xc_handle < 0 )
   1.146 +        return -EINVAL;
   1.147 +
   1.148 +    sysctl.cmd = XEN_SYSCTL_pm_op;
   1.149 +    sysctl.u.pm_op.cmd = SET_CPUFREQ_PARA;
   1.150 +    sysctl.u.pm_op.cpuid = cpuid;
   1.151 +    sysctl.u.pm_op.set_para.ctrl_type = ctrl_type;
   1.152 +    sysctl.u.pm_op.set_para.ctrl_value = ctrl_value;
   1.153 +
   1.154 +    return xc_sysctl(xc_handle, &sysctl);
   1.155 +}
     2.1 --- a/tools/libxc/xenctrl.h	Wed Dec 10 13:27:14 2008 +0000
     2.2 +++ b/tools/libxc/xenctrl.h	Wed Dec 10 13:27:41 2008 +0000
     2.3 @@ -1161,4 +1161,46 @@ int xc_pm_reset_cxstat(int xc_handle, in
     2.4  
     2.5  int xc_cpu_online(int xc_handle, int cpu);
     2.6  int xc_cpu_offline(int xc_handle, int cpu);
     2.7 +
     2.8 +/* 
     2.9 + * cpufreq para name of this structure named 
    2.10 + * same as sysfs file name of native linux
    2.11 + */
    2.12 +typedef xen_userspace_t xc_userspace_t;
    2.13 +typedef xen_ondemand_t xc_ondemand_t;
    2.14 +
    2.15 +struct xc_get_cpufreq_para {
    2.16 +    /* IN/OUT variable */
    2.17 +    uint32_t cpu_num;
    2.18 +    uint32_t freq_num;
    2.19 +    uint32_t gov_num;
    2.20 +
    2.21 +    /* for all governors */
    2.22 +    /* OUT variable */
    2.23 +    uint32_t *affected_cpus;
    2.24 +    uint32_t *scaling_available_frequencies;
    2.25 +    char     *scaling_available_governors;
    2.26 +    char scaling_driver[CPUFREQ_NAME_LEN];
    2.27 +
    2.28 +    uint32_t cpuinfo_cur_freq;
    2.29 +    uint32_t cpuinfo_max_freq;
    2.30 +    uint32_t cpuinfo_min_freq;
    2.31 +    uint32_t scaling_cur_freq;
    2.32 +
    2.33 +    char scaling_governor[CPUFREQ_NAME_LEN];
    2.34 +    uint32_t scaling_max_freq;
    2.35 +    uint32_t scaling_min_freq;
    2.36 +
    2.37 +    /* for specific governor */
    2.38 +    union {
    2.39 +        xc_userspace_t userspace;
    2.40 +        xc_ondemand_t ondemand;
    2.41 +    } u;
    2.42 +};
    2.43 +
    2.44 +int xc_get_cpufreq_para(int xc_handle, int cpuid,
    2.45 +                        struct xc_get_cpufreq_para *user_para);
    2.46 +int xc_set_cpufreq_gov(int xc_handle, int cpuid, char *govname);
    2.47 +int xc_set_cpufreq_para(int xc_handle, int cpuid,
    2.48 +                        int ctrl_type, int ctrl_value);
    2.49  #endif /* XENCTRL_H */
     3.1 --- a/xen/arch/ia64/xen/cpufreq/cpufreq.c	Wed Dec 10 13:27:14 2008 +0000
     3.2 +++ b/xen/arch/ia64/xen/cpufreq/cpufreq.c	Wed Dec 10 13:27:41 2008 +0000
     3.3 @@ -275,6 +275,7 @@ acpi_cpufreq_cpu_exit (struct cpufreq_po
     3.4  }
     3.5  
     3.6  static struct cpufreq_driver acpi_cpufreq_driver = {
     3.7 +	.name       = "acpi-cpufreq",
     3.8  	.verify     = acpi_cpufreq_verify,
     3.9  	.target     = acpi_cpufreq_target,
    3.10  	.get        = acpi_cpufreq_get,
     4.1 --- a/xen/arch/x86/acpi/cpufreq/cpufreq.c	Wed Dec 10 13:27:14 2008 +0000
     4.2 +++ b/xen/arch/x86/acpi/cpufreq/cpufreq.c	Wed Dec 10 13:27:41 2008 +0000
     4.3 @@ -549,6 +549,7 @@ static int acpi_cpufreq_cpu_exit(struct 
     4.4  }
     4.5  
     4.6  static struct cpufreq_driver acpi_cpufreq_driver = {
     4.7 +    .name   = "acpi-cpufreq",
     4.8      .verify = acpi_cpufreq_verify,
     4.9      .target = acpi_cpufreq_target,
    4.10      .init   = acpi_cpufreq_cpu_init,
     5.1 --- a/xen/common/sysctl.c	Wed Dec 10 13:27:14 2008 +0000
     5.2 +++ b/xen/common/sysctl.c	Wed Dec 10 13:27:41 2008 +0000
     5.3 @@ -26,6 +26,7 @@
     5.4  #include <xsm/xsm.h>
     5.5  
     5.6  extern int do_get_pm_info(struct xen_sysctl_get_pmstat *op);
     5.7 +extern int do_pm_op(struct xen_sysctl_pm_op *op);
     5.8  
     5.9  extern long arch_do_sysctl(
    5.10      struct xen_sysctl *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl);
    5.11 @@ -224,6 +225,21 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysc
    5.12      }
    5.13      break;
    5.14  
    5.15 +    case XEN_SYSCTL_pm_op:
    5.16 +    {
    5.17 +        ret = do_pm_op(&op->u.pm_op);
    5.18 +        if ( ret && (ret != -EAGAIN) )
    5.19 +            break;
    5.20 +
    5.21 +        if ( op->u.pm_op.cmd == GET_CPUFREQ_PARA )
    5.22 +            if ( copy_to_guest(u_sysctl, op, 1) )
    5.23 +            {
    5.24 +                ret = -EFAULT;
    5.25 +                break;
    5.26 +            }
    5.27 +    }
    5.28 +    break;
    5.29 +
    5.30      default:
    5.31          ret = arch_do_sysctl(op, u_sysctl);
    5.32          break;
     6.1 --- a/xen/drivers/acpi/pmstat.c	Wed Dec 10 13:27:14 2008 +0000
     6.2 +++ b/xen/drivers/acpi/pmstat.c	Wed Dec 10 13:27:41 2008 +0000
     6.3 @@ -47,6 +47,11 @@ extern uint32_t pmstat_get_cx_nr(uint32_
     6.4  extern int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat);
     6.5  extern int pmstat_reset_cx_stat(uint32_t cpuid);
     6.6  
     6.7 +extern struct list_head cpufreq_governor_list;
     6.8 +
     6.9 +/*
    6.10 + * Get PM statistic info
    6.11 + */
    6.12  int do_get_pm_info(struct xen_sysctl_get_pmstat *op)
    6.13  {
    6.14      int ret = 0;
    6.15 @@ -156,3 +161,304 @@ int do_get_pm_info(struct xen_sysctl_get
    6.16  
    6.17      return ret;
    6.18  }
    6.19 +
    6.20 +/*
    6.21 + * 1. Get PM parameter
    6.22 + * 2. Provide user PM control
    6.23 + */
    6.24 +static int read_scaling_available_governors(char *scaling_available_governors,
    6.25 +                                            unsigned int size)
    6.26 +{
    6.27 +    unsigned int i = 0;
    6.28 +    struct cpufreq_governor *t;
    6.29 +
    6.30 +    if ( !scaling_available_governors )
    6.31 +        return -EINVAL;
    6.32 +
    6.33 +    list_for_each_entry(t, &cpufreq_governor_list, governor_list)
    6.34 +    {
    6.35 +        i += scnprintf(&scaling_available_governors[i],
    6.36 +                       CPUFREQ_NAME_LEN, "%s ", t->name);
    6.37 +        if ( i > size )
    6.38 +            return -EINVAL;
    6.39 +    }
    6.40 +    scaling_available_governors[i-1] = '\0';
    6.41 +
    6.42 +    return 0;
    6.43 +}
    6.44 +
    6.45 +static int get_cpufreq_para(struct xen_sysctl_pm_op *op)
    6.46 +{
    6.47 +    uint32_t ret = 0;
    6.48 +    const struct processor_pminfo *pmpt;
    6.49 +    struct cpufreq_policy *policy;
    6.50 +    uint32_t gov_num = 0;
    6.51 +    uint32_t *affected_cpus;
    6.52 +    uint32_t *scaling_available_frequencies;
    6.53 +    char     *scaling_available_governors;
    6.54 +    struct list_head *pos;
    6.55 +    uint32_t cpu, i, j = 0;
    6.56 +
    6.57 +    if ( !op || !cpu_online(op->cpuid) )
    6.58 +        return -EINVAL;
    6.59 +    pmpt = processor_pminfo[op->cpuid];
    6.60 +    policy = cpufreq_cpu_policy[op->cpuid];
    6.61 +
    6.62 +    if ( !pmpt || !pmpt->perf.states ||
    6.63 +         !policy || !policy->governor )
    6.64 +        return -EINVAL;
    6.65 +
    6.66 +    list_for_each(pos, &cpufreq_governor_list)
    6.67 +        gov_num++;
    6.68 +
    6.69 +    if ( (op->get_para.cpu_num  != cpus_weight(policy->cpus)) ||
    6.70 +         (op->get_para.freq_num != pmpt->perf.state_count)    ||
    6.71 +         (op->get_para.gov_num  != gov_num) )
    6.72 +    {
    6.73 +        op->get_para.cpu_num =  cpus_weight(policy->cpus);
    6.74 +        op->get_para.freq_num = pmpt->perf.state_count;
    6.75 +        op->get_para.gov_num  = gov_num;
    6.76 +        return -EAGAIN;
    6.77 +    }
    6.78 +
    6.79 +    if ( !(affected_cpus = xmalloc_array(uint32_t, op->get_para.cpu_num)) )
    6.80 +        return -ENOMEM;
    6.81 +    memset(affected_cpus, 0, op->get_para.cpu_num * sizeof(uint32_t));
    6.82 +    for_each_cpu_mask(cpu, policy->cpus)
    6.83 +        affected_cpus[j++] = cpu;
    6.84 +    ret = copy_to_guest(op->get_para.affected_cpus,
    6.85 +                       affected_cpus, op->get_para.cpu_num);
    6.86 +    xfree(affected_cpus);
    6.87 +    if ( ret )
    6.88 +        return ret;
    6.89 +
    6.90 +    if ( !(scaling_available_frequencies =
    6.91 +        xmalloc_array(uint32_t, op->get_para.freq_num)) )
    6.92 +        return -ENOMEM;
    6.93 +    memset(scaling_available_frequencies, 0,
    6.94 +           op->get_para.freq_num * sizeof(uint32_t));
    6.95 +    for ( i = 0; i < op->get_para.freq_num; i++ )
    6.96 +        scaling_available_frequencies[i] =
    6.97 +                        pmpt->perf.states[i].core_frequency * 1000;
    6.98 +    ret = copy_to_guest(op->get_para.scaling_available_frequencies,
    6.99 +                   scaling_available_frequencies, op->get_para.freq_num);
   6.100 +    xfree(scaling_available_frequencies);
   6.101 +    if ( ret )
   6.102 +        return ret;
   6.103 +
   6.104 +    if ( !(scaling_available_governors =
   6.105 +        xmalloc_array(char, gov_num * CPUFREQ_NAME_LEN)) )
   6.106 +        return -ENOMEM;
   6.107 +    memset(scaling_available_governors, 0,
   6.108 +                gov_num * CPUFREQ_NAME_LEN * sizeof(char));
   6.109 +    if ( (ret = read_scaling_available_governors(scaling_available_governors,
   6.110 +                gov_num * CPUFREQ_NAME_LEN * sizeof(char))) )
   6.111 +    {
   6.112 +        xfree(scaling_available_governors);
   6.113 +        return ret;
   6.114 +    }
   6.115 +    ret = copy_to_guest(op->get_para.scaling_available_governors,
   6.116 +                scaling_available_governors, gov_num * CPUFREQ_NAME_LEN);
   6.117 +    xfree(scaling_available_governors);
   6.118 +    if ( ret )
   6.119 +        return ret;
   6.120 +
   6.121 +    op->get_para.cpuinfo_cur_freq =
   6.122 +        cpufreq_driver->get ? cpufreq_driver->get(op->cpuid) : policy->cur;
   6.123 +    op->get_para.cpuinfo_max_freq = policy->cpuinfo.max_freq;
   6.124 +    op->get_para.cpuinfo_min_freq = policy->cpuinfo.min_freq;
   6.125 +    op->get_para.scaling_cur_freq = policy->cur;
   6.126 +    op->get_para.scaling_max_freq = policy->max;
   6.127 +    op->get_para.scaling_min_freq = policy->min;
   6.128 +
   6.129 +    if ( cpufreq_driver->name )
   6.130 +        strlcpy(op->get_para.scaling_driver, 
   6.131 +            cpufreq_driver->name, CPUFREQ_NAME_LEN);
   6.132 +    else
   6.133 +        strlcpy(op->get_para.scaling_driver, "Unknown", CPUFREQ_NAME_LEN);
   6.134 +
   6.135 +    if ( policy->governor->name )
   6.136 +        strlcpy(op->get_para.scaling_governor, 
   6.137 +            policy->governor->name, CPUFREQ_NAME_LEN);
   6.138 +    else
   6.139 +        strlcpy(op->get_para.scaling_governor, "Unknown", CPUFREQ_NAME_LEN);
   6.140 +
   6.141 +    /* governor specific para */
   6.142 +    if ( !strnicmp(op->get_para.scaling_governor, 
   6.143 +                   "userspace", CPUFREQ_NAME_LEN) )
   6.144 +    {
   6.145 +        op->get_para.u.userspace.scaling_setspeed = policy->cur;
   6.146 +    }
   6.147 +
   6.148 +    if ( !strnicmp(op->get_para.scaling_governor, 
   6.149 +                   "ondemand", CPUFREQ_NAME_LEN) )
   6.150 +    {
   6.151 +        ret = get_cpufreq_ondemand_para(
   6.152 +            &op->get_para.u.ondemand.sampling_rate_max,
   6.153 +            &op->get_para.u.ondemand.sampling_rate_min,
   6.154 +            &op->get_para.u.ondemand.sampling_rate,
   6.155 +            &op->get_para.u.ondemand.up_threshold); 
   6.156 +    }
   6.157 +
   6.158 +    return ret;
   6.159 +}
   6.160 +
   6.161 +static int set_cpufreq_gov(struct xen_sysctl_pm_op *op)
   6.162 +{
   6.163 +    struct cpufreq_policy new_policy, *old_policy;
   6.164 +
   6.165 +    if ( !op || !cpu_online(op->cpuid) )
   6.166 +        return -EINVAL;
   6.167 +
   6.168 +    old_policy = cpufreq_cpu_policy[op->cpuid];
   6.169 +    if ( !old_policy )
   6.170 +        return -EINVAL;
   6.171 +
   6.172 +    memcpy(&new_policy, old_policy, sizeof(struct cpufreq_policy));
   6.173 +
   6.174 +    new_policy.governor = __find_governor(op->set_gov.scaling_governor);
   6.175 +    if (new_policy.governor == NULL)
   6.176 +        return -EINVAL;
   6.177 +
   6.178 +    return __cpufreq_set_policy(old_policy, &new_policy);
   6.179 +}
   6.180 +
   6.181 +static int set_cpufreq_para(struct xen_sysctl_pm_op *op)
   6.182 +{
   6.183 +    int ret = 0;
   6.184 +    struct cpufreq_policy *policy;
   6.185 +
   6.186 +    if ( !op || !cpu_online(op->cpuid) )
   6.187 +        return -EINVAL;
   6.188 +    policy = cpufreq_cpu_policy[op->cpuid];
   6.189 +
   6.190 +    if ( !policy || !policy->governor )
   6.191 +        return -EINVAL;
   6.192 +
   6.193 +    switch(op->set_para.ctrl_type)
   6.194 +    {
   6.195 +    case SCALING_MAX_FREQ:
   6.196 +    {
   6.197 +        struct cpufreq_policy new_policy;
   6.198 +
   6.199 +        memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
   6.200 +        new_policy.max = op->set_para.ctrl_value;
   6.201 +        ret = __cpufreq_set_policy(policy, &new_policy);
   6.202 +
   6.203 +        break;
   6.204 +    }
   6.205 +
   6.206 +    case SCALING_MIN_FREQ:
   6.207 +    {
   6.208 +        struct cpufreq_policy new_policy;
   6.209 +
   6.210 +        memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
   6.211 +        new_policy.min = op->set_para.ctrl_value;
   6.212 +        ret = __cpufreq_set_policy(policy, &new_policy);
   6.213 +
   6.214 +        break;
   6.215 +    }
   6.216 +
   6.217 +    case SCALING_SETSPEED:
   6.218 +    {
   6.219 +        unsigned int freq =op->set_para.ctrl_value;
   6.220 +
   6.221 +        if ( !strnicmp(policy->governor->name,
   6.222 +                       "userspace", CPUFREQ_NAME_LEN) )
   6.223 +        {
   6.224 +            if ( freq < policy->min )
   6.225 +                freq = policy->min;
   6.226 +            if ( freq > policy->max )
   6.227 +                freq = policy->max;
   6.228 +
   6.229 +            ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
   6.230 +        }
   6.231 +        else
   6.232 +            ret = -EINVAL;
   6.233 +
   6.234 +        break;
   6.235 +    }
   6.236 +
   6.237 +    case SAMPLING_RATE:
   6.238 +    {
   6.239 +        unsigned int sampling_rate = op->set_para.ctrl_value;
   6.240 +
   6.241 +        if ( !strnicmp(policy->governor->name,
   6.242 +                       "ondemand", CPUFREQ_NAME_LEN) )
   6.243 +            ret = write_ondemand_sampling_rate(sampling_rate);
   6.244 +        else
   6.245 +            ret = -EINVAL;
   6.246 +
   6.247 +        break;
   6.248 +    }
   6.249 +
   6.250 +    case UP_THRESHOLD:
   6.251 +    {
   6.252 +        unsigned int up_threshold = op->set_para.ctrl_value;
   6.253 +
   6.254 +        if ( !strnicmp(policy->governor->name,
   6.255 +                       "ondemand", CPUFREQ_NAME_LEN) )
   6.256 +            ret = write_ondemand_up_threshold(up_threshold);
   6.257 +        else
   6.258 +            ret = -EINVAL;
   6.259 +
   6.260 +        break;
   6.261 +    }
   6.262 +
   6.263 +    default:
   6.264 +        ret = -EINVAL;
   6.265 +        break;
   6.266 +    }
   6.267 +
   6.268 +    return ret;
   6.269 +}
   6.270 +
   6.271 +int do_pm_op(struct xen_sysctl_pm_op *op)
   6.272 +{
   6.273 +    int ret = 0;
   6.274 +    const struct processor_pminfo *pmpt;
   6.275 +
   6.276 +    if ( !op || !cpu_online(op->cpuid) )
   6.277 +        return -EINVAL;
   6.278 +    pmpt = processor_pminfo[op->cpuid];
   6.279 +
   6.280 +    switch ( op->cmd & PM_PARA_CATEGORY_MASK )
   6.281 +    {
   6.282 +    case CPUFREQ_PARA:
   6.283 +        if ( !(xen_processor_pmbits & XEN_PROCESSOR_PM_PX) )
   6.284 +            return -ENODEV;
   6.285 +        if ( !pmpt || !(pmpt->perf.init & XEN_PX_INIT) )
   6.286 +            return -EINVAL;
   6.287 +        break;
   6.288 +    default:
   6.289 +        return -ENODEV;
   6.290 +    }
   6.291 +
   6.292 +    switch ( op->cmd )
   6.293 +    {
   6.294 +    case GET_CPUFREQ_PARA:
   6.295 +    {
   6.296 +        ret = get_cpufreq_para(op);
   6.297 +        break;
   6.298 +    }
   6.299 +
   6.300 +    case SET_CPUFREQ_GOV:
   6.301 +    {
   6.302 +        ret = set_cpufreq_gov(op);
   6.303 +        break;
   6.304 +    }
   6.305 +
   6.306 +    case SET_CPUFREQ_PARA:
   6.307 +    {
   6.308 +        ret = set_cpufreq_para(op);
   6.309 +        break;
   6.310 +    }
   6.311 +
   6.312 +    default:
   6.313 +        printk("not defined sub-hypercall @ do_pm_op\n");
   6.314 +        ret = -ENOSYS;
   6.315 +        break;
   6.316 +    }
   6.317 +
   6.318 +    return ret;
   6.319 +}
     7.1 --- a/xen/drivers/cpufreq/cpufreq.c	Wed Dec 10 13:27:14 2008 +0000
     7.2 +++ b/xen/drivers/cpufreq/cpufreq.c	Wed Dec 10 13:27:41 2008 +0000
     7.3 @@ -53,9 +53,9 @@ struct cpufreq_dom {
     7.4  };
     7.5  static LIST_HEAD(cpufreq_dom_list_head);
     7.6  
     7.7 -static LIST_HEAD(cpufreq_governor_list);
     7.8 +LIST_HEAD(cpufreq_governor_list);
     7.9  
    7.10 -static struct cpufreq_governor *__find_governor(const char *governor)
    7.11 +struct cpufreq_governor *__find_governor(const char *governor)
    7.12  {
    7.13      struct cpufreq_governor *t;
    7.14  
     8.1 --- a/xen/drivers/cpufreq/cpufreq_ondemand.c	Wed Dec 10 13:27:14 2008 +0000
     8.2 +++ b/xen/drivers/cpufreq/cpufreq_ondemand.c	Wed Dec 10 13:27:41 2008 +0000
     8.3 @@ -51,12 +51,50 @@ static struct dbs_tuners {
     8.4      unsigned int up_threshold;
     8.5      unsigned int powersave_bias;
     8.6  } dbs_tuners_ins = {
     8.7 +    .sampling_rate = 0,
     8.8      .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
     8.9      .powersave_bias = 0,
    8.10  };
    8.11  
    8.12  static struct timer dbs_timer[NR_CPUS];
    8.13  
    8.14 +int write_ondemand_sampling_rate(unsigned int sampling_rate)
    8.15 +{
    8.16 +    if ( (sampling_rate > MAX_SAMPLING_RATE / MICROSECS(1)) ||
    8.17 +         (sampling_rate < MIN_SAMPLING_RATE / MICROSECS(1)) )
    8.18 +        return -EINVAL;
    8.19 +
    8.20 +    dbs_tuners_ins.sampling_rate = sampling_rate * MICROSECS(1);
    8.21 +    return 0;
    8.22 +}
    8.23 +
    8.24 +int write_ondemand_up_threshold(unsigned int up_threshold)
    8.25 +{
    8.26 +    if ( (up_threshold > MAX_FREQUENCY_UP_THRESHOLD) ||
    8.27 +         (up_threshold < MIN_FREQUENCY_UP_THRESHOLD) )
    8.28 +        return -EINVAL;
    8.29 +
    8.30 +    dbs_tuners_ins.up_threshold = up_threshold;
    8.31 +    return 0;
    8.32 +}
    8.33 +
    8.34 +int get_cpufreq_ondemand_para(uint32_t *sampling_rate_max,
    8.35 +                              uint32_t *sampling_rate_min,
    8.36 +                              uint32_t *sampling_rate,
    8.37 +                              uint32_t *up_threshold)
    8.38 +{
    8.39 +    if (!sampling_rate_max || !sampling_rate_min ||
    8.40 +        !sampling_rate || !up_threshold)
    8.41 +        return -EINVAL;
    8.42 +
    8.43 +    *sampling_rate_max = MAX_SAMPLING_RATE/MICROSECS(1);
    8.44 +    *sampling_rate_min = MIN_SAMPLING_RATE/MICROSECS(1);
    8.45 +    *sampling_rate = dbs_tuners_ins.sampling_rate / MICROSECS(1);
    8.46 +    *up_threshold = dbs_tuners_ins.up_threshold;
    8.47 +
    8.48 +    return 0;
    8.49 +}
    8.50 +
    8.51  uint64_t get_cpu_idle_time(unsigned int cpu)
    8.52  {
    8.53      uint64_t idle_ns;
    8.54 @@ -214,7 +252,7 @@ int cpufreq_governor_dbs(struct cpufreq_
    8.55           * Start the timerschedule work, when this governor
    8.56           * is used for first time
    8.57           */
    8.58 -        if (dbs_enable == 1) {
    8.59 +        if ((dbs_enable == 1) && !dbs_tuners_ins.sampling_rate) {
    8.60              def_sampling_rate = policy->cpuinfo.transition_latency *
    8.61                  DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;
    8.62  
     9.1 --- a/xen/include/acpi/cpufreq/cpufreq.h	Wed Dec 10 13:27:14 2008 +0000
     9.2 +++ b/xen/include/acpi/cpufreq/cpufreq.h	Wed Dec 10 13:27:41 2008 +0000
     9.3 @@ -17,8 +17,6 @@
     9.4  
     9.5  #include "processor_perf.h"
     9.6  
     9.7 -#define CPUFREQ_NAME_LEN 16
     9.8 -
     9.9  struct cpufreq_governor;
    9.10  
    9.11  struct acpi_cpufreq_data {
    9.12 @@ -88,9 +86,14 @@ struct cpufreq_governor {
    9.13  };
    9.14  
    9.15  extern struct cpufreq_governor cpufreq_gov_dbs;
    9.16 +extern struct cpufreq_governor cpufreq_gov_userspace;
    9.17 +extern struct cpufreq_governor cpufreq_gov_performance;
    9.18 +extern struct cpufreq_governor cpufreq_gov_powersave;
    9.19 +
    9.20  extern int cpufreq_register_governor(struct cpufreq_governor *governor);
    9.21  extern int cpufreq_unregister_governor(struct cpufreq_governor *governor);
    9.22 -#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_dbs
    9.23 +extern struct cpufreq_governor *__find_governor(const char *governor);
    9.24 +#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_performance
    9.25  
    9.26  /* pass a target to the cpufreq driver */
    9.27  extern int __cpufreq_driver_target(struct cpufreq_policy *policy,
    9.28 @@ -113,6 +116,7 @@ static __inline__ int
    9.29  #define CPUFREQ_RELATION_H 1  /* highest frequency below or at target */
    9.30  
    9.31  struct cpufreq_driver {
    9.32 +    char   name[CPUFREQ_NAME_LEN];
    9.33      int    (*init)(struct cpufreq_policy *policy);
    9.34      int    (*verify)(struct cpufreq_policy *policy);
    9.35      int    (*target)(struct cpufreq_policy *policy,
    9.36 @@ -210,3 +214,9 @@ struct cpu_dbs_info_s {
    9.37  };
    9.38  
    9.39  int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event);
    9.40 +int get_cpufreq_ondemand_para(uint32_t *sampling_rate_max,
    9.41 +                              uint32_t *sampling_rate_min,
    9.42 +                              uint32_t *sampling_rate,
    9.43 +                              uint32_t *up_threshold);
    9.44 +int write_ondemand_sampling_rate(unsigned int sampling_rate);
    9.45 +int write_ondemand_up_threshold(unsigned int up_threshold);
    10.1 --- a/xen/include/public/sysctl.h	Wed Dec 10 13:27:14 2008 +0000
    10.2 +++ b/xen/include/public/sysctl.h	Wed Dec 10 13:27:41 2008 +0000
    10.3 @@ -273,6 +273,91 @@ struct xen_sysctl_cpu_hotplug {
    10.4  typedef struct xen_sysctl_cpu_hotplug xen_sysctl_cpu_hotplug_t;
    10.5  DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpu_hotplug_t);
    10.6  
    10.7 +/*
    10.8 + * Get/set xen power management, include 
    10.9 + * 1. cpufreq governors and related parameters
   10.10 + */
   10.11 +#define XEN_SYSCTL_pm_op        12
   10.12 +struct xen_userspace {
   10.13 +    uint32_t scaling_setspeed;
   10.14 +};
   10.15 +typedef struct xen_userspace xen_userspace_t;
   10.16 +
   10.17 +struct xen_ondemand {
   10.18 +    uint32_t sampling_rate_max;
   10.19 +    uint32_t sampling_rate_min;
   10.20 +
   10.21 +    uint32_t sampling_rate;
   10.22 +    uint32_t up_threshold;
   10.23 +};
   10.24 +typedef struct xen_ondemand xen_ondemand_t;
   10.25 +
   10.26 +/* 
   10.27 + * cpufreq para name of this structure named 
   10.28 + * same as sysfs file name of native linux
   10.29 + */
   10.30 +#define CPUFREQ_NAME_LEN 16
   10.31 +struct xen_get_cpufreq_para {
   10.32 +    /* IN/OUT variable */
   10.33 +    uint32_t cpu_num;
   10.34 +    uint32_t freq_num;
   10.35 +    uint32_t gov_num;
   10.36 +
   10.37 +    /* for all governors */
   10.38 +    /* OUT variable */
   10.39 +    XEN_GUEST_HANDLE_64(uint32) affected_cpus;
   10.40 +    XEN_GUEST_HANDLE_64(uint32) scaling_available_frequencies;
   10.41 +    XEN_GUEST_HANDLE_64(char)   scaling_available_governors;
   10.42 +    char scaling_driver[CPUFREQ_NAME_LEN];
   10.43 +
   10.44 +    uint32_t cpuinfo_cur_freq;
   10.45 +    uint32_t cpuinfo_max_freq;
   10.46 +    uint32_t cpuinfo_min_freq;
   10.47 +    uint32_t scaling_cur_freq;
   10.48 +
   10.49 +    char scaling_governor[CPUFREQ_NAME_LEN];
   10.50 +    uint32_t scaling_max_freq;
   10.51 +    uint32_t scaling_min_freq;
   10.52 +
   10.53 +    /* for specific governor */
   10.54 +    union {
   10.55 +        struct  xen_userspace userspace;
   10.56 +        struct  xen_ondemand ondemand;
   10.57 +    } u;
   10.58 +};
   10.59 +
   10.60 +struct xen_set_cpufreq_gov {
   10.61 +    char scaling_governor[CPUFREQ_NAME_LEN];
   10.62 +};
   10.63 +
   10.64 +struct xen_set_cpufreq_para {
   10.65 +    #define SCALING_MAX_FREQ           1
   10.66 +    #define SCALING_MIN_FREQ           2
   10.67 +    #define SCALING_SETSPEED           3
   10.68 +    #define SAMPLING_RATE              4
   10.69 +    #define UP_THRESHOLD               5
   10.70 +
   10.71 +    uint32_t ctrl_type;
   10.72 +    uint32_t ctrl_value;
   10.73 +};
   10.74 +
   10.75 +struct xen_sysctl_pm_op {
   10.76 +    #define PM_PARA_CATEGORY_MASK      0xf0
   10.77 +    #define CPUFREQ_PARA               0x10
   10.78 +
   10.79 +    /* cpufreq command type */
   10.80 +    #define GET_CPUFREQ_PARA           (CPUFREQ_PARA | 0x01)
   10.81 +    #define SET_CPUFREQ_GOV            (CPUFREQ_PARA | 0x02)
   10.82 +    #define SET_CPUFREQ_PARA           (CPUFREQ_PARA | 0x03)
   10.83 +
   10.84 +    uint32_t cmd;
   10.85 +    uint32_t cpuid;
   10.86 +    union {
   10.87 +        struct xen_get_cpufreq_para get_para;
   10.88 +        struct xen_set_cpufreq_gov  set_gov;
   10.89 +        struct xen_set_cpufreq_para set_para;
   10.90 +    };
   10.91 +};
   10.92  
   10.93  struct xen_sysctl {
   10.94      uint32_t cmd;
   10.95 @@ -289,6 +374,7 @@ struct xen_sysctl {
   10.96          struct xen_sysctl_availheap         availheap;
   10.97          struct xen_sysctl_get_pmstat        get_pmstat;
   10.98          struct xen_sysctl_cpu_hotplug       cpu_hotplug;
   10.99 +        struct xen_sysctl_pm_op             pm_op;
  10.100          uint8_t                             pad[128];
  10.101      } u;
  10.102  };