[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Add user PM control interface



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1228915661 0
# Node ID 605ef79ee46c5d57ee0797ac69521c263b62bce9
# Parent  9ba1541d6dc2d6c6e6c7cf0a57ef8a1f0ea9793d
Add user PM control interface

Signed-off-by: Liu, Jinsong <jinsong.liu@xxxxxxxxx>
---
 tools/libxc/xc_pm.c                    |  140 +++++++++++++++
 tools/libxc/xenctrl.h                  |   42 ++++
 xen/arch/ia64/xen/cpufreq/cpufreq.c    |    1 
 xen/arch/x86/acpi/cpufreq/cpufreq.c    |    1 
 xen/common/sysctl.c                    |   16 +
 xen/drivers/acpi/pmstat.c              |  306 +++++++++++++++++++++++++++++++++
 xen/drivers/cpufreq/cpufreq.c          |    6 
 xen/drivers/cpufreq/cpufreq_ondemand.c |   40 ++++
 xen/include/acpi/cpufreq/cpufreq.h     |   16 +
 xen/include/public/sysctl.h            |   86 +++++++++
 10 files changed, 647 insertions(+), 7 deletions(-)

diff -r 9ba1541d6dc2 -r 605ef79ee46c tools/libxc/xc_pm.c
--- a/tools/libxc/xc_pm.c       Wed Dec 10 13:27:14 2008 +0000
+++ b/tools/libxc/xc_pm.c       Wed Dec 10 13:27:41 2008 +0000
@@ -23,8 +23,15 @@
  *
  */
 
+#include <errno.h>
+#include <curses.h>
+#include <linux/kernel.h>
+
 #include "xc_private.h"
 
+/*
+ * Get PM statistic info
+ */
 int xc_pm_get_max_px(int xc_handle, int cpuid, int *max_px)
 {
     DECLARE_SYSCTL;
@@ -168,3 +175,136 @@ int xc_pm_reset_cxstat(int xc_handle, in
 
     return xc_sysctl(xc_handle, &sysctl);
 }
+
+
+/*
+ * 1. Get PM parameter
+ * 2. Provide user PM control
+ */
+int xc_get_cpufreq_para(int xc_handle, int cpuid,
+                        struct xc_get_cpufreq_para *user_para)
+{
+    DECLARE_SYSCTL;
+    int ret = 0;
+    struct xen_get_cpufreq_para *sys_para = &sysctl.u.pm_op.get_para;
+    bool has_num = user_para->cpu_num &&
+                     user_para->freq_num &&
+                     user_para->gov_num;
+
+    if ( (xc_handle < 0) || !user_para )
+        return -EINVAL;
+
+    if ( has_num )
+    {
+        if ( (!user_para->affected_cpus)                    ||
+             (!user_para->scaling_available_frequencies)    ||
+             (!user_para->scaling_available_governors) )
+            return -EINVAL;
+
+        if ( (ret = lock_pages(user_para->affected_cpus,
+                               user_para->cpu_num * sizeof(uint32_t))) )
+            goto unlock_1;
+        if ( (ret = lock_pages(user_para->scaling_available_frequencies,
+                               user_para->freq_num * sizeof(uint32_t))) )
+            goto unlock_2;
+        if ( (ret = lock_pages(user_para->scaling_available_governors,
+                 user_para->gov_num * CPUFREQ_NAME_LEN * sizeof(char))) )
+            goto unlock_3;
+
+        set_xen_guest_handle(sys_para->affected_cpus,
+                             user_para->affected_cpus);
+        set_xen_guest_handle(sys_para->scaling_available_frequencies,
+                             user_para->scaling_available_frequencies);
+        set_xen_guest_handle(sys_para->scaling_available_governors,
+                             user_para->scaling_available_governors);
+    }
+
+    sysctl.cmd = XEN_SYSCTL_pm_op;
+    sysctl.u.pm_op.cmd = GET_CPUFREQ_PARA;
+    sysctl.u.pm_op.cpuid = cpuid;
+    sys_para->cpu_num  = user_para->cpu_num;
+    sys_para->freq_num = user_para->freq_num;
+    sys_para->gov_num  = user_para->gov_num;
+
+    ret = xc_sysctl(xc_handle, &sysctl);
+    if ( ret )
+    {
+        if ( errno == EAGAIN )
+        {
+            user_para->cpu_num  = sys_para->cpu_num;
+            user_para->freq_num = sys_para->freq_num;
+            user_para->gov_num  = sys_para->gov_num;
+            ret = -errno;
+        }
+
+        if ( has_num )
+            goto unlock_4;
+        goto unlock_1;
+    }
+    else
+    {
+        user_para->cpuinfo_cur_freq = sys_para->cpuinfo_cur_freq;
+        user_para->cpuinfo_max_freq = sys_para->cpuinfo_max_freq;
+        user_para->cpuinfo_min_freq = sys_para->cpuinfo_min_freq;
+        user_para->scaling_cur_freq = sys_para->scaling_cur_freq;
+        user_para->scaling_max_freq = sys_para->scaling_max_freq;
+        user_para->scaling_min_freq = sys_para->scaling_min_freq;
+
+        memcpy(user_para->scaling_driver, 
+                sys_para->scaling_driver, CPUFREQ_NAME_LEN);
+        memcpy(user_para->scaling_governor,
+                sys_para->scaling_governor, CPUFREQ_NAME_LEN);
+
+        /* copy to user_para no matter what cpufreq governor */
+        BUILD_BUG_ON(sizeof(((struct xc_get_cpufreq_para *)0)->u) !=
+                     sizeof(((struct xen_get_cpufreq_para *)0)->u));
+
+        memcpy(&user_para->u, &sys_para->u, sizeof(sys_para->u));
+    }
+
+unlock_4:
+    unlock_pages(user_para->scaling_available_governors,
+                 user_para->gov_num * CPUFREQ_NAME_LEN * sizeof(char));
+unlock_3:
+    unlock_pages(user_para->scaling_available_frequencies,
+                 user_para->freq_num * sizeof(uint32_t));
+unlock_2:
+    unlock_pages(user_para->affected_cpus,
+                 user_para->cpu_num * sizeof(uint32_t));
+unlock_1:
+    return ret;
+}
+
+int xc_set_cpufreq_gov(int xc_handle, int cpuid, char *govname)
+{
+    DECLARE_SYSCTL;
+    char *scaling_governor = sysctl.u.pm_op.set_gov.scaling_governor;
+
+    if ( (xc_handle < 0) || (!govname) )
+        return -EINVAL;
+
+    sysctl.cmd = XEN_SYSCTL_pm_op;
+    sysctl.u.pm_op.cmd = SET_CPUFREQ_GOV;
+    sysctl.u.pm_op.cpuid = cpuid;
+    strncpy(scaling_governor, govname, CPUFREQ_NAME_LEN);
+    scaling_governor[CPUFREQ_NAME_LEN] = '\0';
+
+    return xc_sysctl(xc_handle, &sysctl);
+}
+
+int xc_set_cpufreq_para(int xc_handle, int cpuid, 
+                        int ctrl_type, int ctrl_value)
+{
+    DECLARE_SYSCTL;
+
+    if ( xc_handle < 0 )
+        return -EINVAL;
+
+    sysctl.cmd = XEN_SYSCTL_pm_op;
+    sysctl.u.pm_op.cmd = SET_CPUFREQ_PARA;
+    sysctl.u.pm_op.cpuid = cpuid;
+    sysctl.u.pm_op.set_para.ctrl_type = ctrl_type;
+    sysctl.u.pm_op.set_para.ctrl_value = ctrl_value;
+
+    return xc_sysctl(xc_handle, &sysctl);
+}
diff -r 9ba1541d6dc2 -r 605ef79ee46c tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Wed Dec 10 13:27:14 2008 +0000
+++ b/tools/libxc/xenctrl.h     Wed Dec 10 13:27:41 2008 +0000
@@ -1161,4 +1161,46 @@ int xc_pm_reset_cxstat(int xc_handle, in
 
 int xc_cpu_online(int xc_handle, int cpu);
 int xc_cpu_offline(int xc_handle, int cpu);
+
+/* 
+ * cpufreq para name of this structure named 
+ * same as sysfs file name of native linux
+ */
+typedef xen_userspace_t xc_userspace_t;
+typedef xen_ondemand_t xc_ondemand_t;
+
+struct xc_get_cpufreq_para {
+    /* IN/OUT variable */
+    uint32_t cpu_num;
+    uint32_t freq_num;
+    uint32_t gov_num;
+
+    /* for all governors */
+    /* OUT variable */
+    uint32_t *affected_cpus;
+    uint32_t *scaling_available_frequencies;
+    char     *scaling_available_governors;
+    char scaling_driver[CPUFREQ_NAME_LEN];
+
+    uint32_t cpuinfo_cur_freq;
+    uint32_t cpuinfo_max_freq;
+    uint32_t cpuinfo_min_freq;
+    uint32_t scaling_cur_freq;
+
+    char scaling_governor[CPUFREQ_NAME_LEN];
+    uint32_t scaling_max_freq;
+    uint32_t scaling_min_freq;
+
+    /* for specific governor */
+    union {
+        xc_userspace_t userspace;
+        xc_ondemand_t ondemand;
+    } u;
+};
+
+int xc_get_cpufreq_para(int xc_handle, int cpuid,
+                        struct xc_get_cpufreq_para *user_para);
+int xc_set_cpufreq_gov(int xc_handle, int cpuid, char *govname);
+int xc_set_cpufreq_para(int xc_handle, int cpuid,
+                        int ctrl_type, int ctrl_value);
 #endif /* XENCTRL_H */
diff -r 9ba1541d6dc2 -r 605ef79ee46c xen/arch/ia64/xen/cpufreq/cpufreq.c
--- a/xen/arch/ia64/xen/cpufreq/cpufreq.c       Wed Dec 10 13:27:14 2008 +0000
+++ b/xen/arch/ia64/xen/cpufreq/cpufreq.c       Wed Dec 10 13:27:41 2008 +0000
@@ -275,6 +275,7 @@ acpi_cpufreq_cpu_exit (struct cpufreq_po
 }
 
 static struct cpufreq_driver acpi_cpufreq_driver = {
+       .name       = "acpi-cpufreq",
        .verify     = acpi_cpufreq_verify,
        .target     = acpi_cpufreq_target,
        .get        = acpi_cpufreq_get,
diff -r 9ba1541d6dc2 -r 605ef79ee46c xen/arch/x86/acpi/cpufreq/cpufreq.c
--- a/xen/arch/x86/acpi/cpufreq/cpufreq.c       Wed Dec 10 13:27:14 2008 +0000
+++ b/xen/arch/x86/acpi/cpufreq/cpufreq.c       Wed Dec 10 13:27:41 2008 +0000
@@ -549,6 +549,7 @@ static int acpi_cpufreq_cpu_exit(struct 
 }
 
 static struct cpufreq_driver acpi_cpufreq_driver = {
+    .name   = "acpi-cpufreq",
     .verify = acpi_cpufreq_verify,
     .target = acpi_cpufreq_target,
     .init   = acpi_cpufreq_cpu_init,
diff -r 9ba1541d6dc2 -r 605ef79ee46c xen/common/sysctl.c
--- a/xen/common/sysctl.c       Wed Dec 10 13:27:14 2008 +0000
+++ b/xen/common/sysctl.c       Wed Dec 10 13:27:41 2008 +0000
@@ -26,6 +26,7 @@
 #include <xsm/xsm.h>
 
 extern int do_get_pm_info(struct xen_sysctl_get_pmstat *op);
+extern int do_pm_op(struct xen_sysctl_pm_op *op);
 
 extern long arch_do_sysctl(
     struct xen_sysctl *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl);
@@ -221,6 +222,21 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysc
             ret = -EFAULT;
             break;
         }
+    }
+    break;
+
+    case XEN_SYSCTL_pm_op:
+    {
+        ret = do_pm_op(&op->u.pm_op);
+        if ( ret && (ret != -EAGAIN) )
+            break;
+
+        if ( op->u.pm_op.cmd == GET_CPUFREQ_PARA )
+            if ( copy_to_guest(u_sysctl, op, 1) )
+            {
+                ret = -EFAULT;
+                break;
+            }
     }
     break;
 
diff -r 9ba1541d6dc2 -r 605ef79ee46c xen/drivers/acpi/pmstat.c
--- a/xen/drivers/acpi/pmstat.c Wed Dec 10 13:27:14 2008 +0000
+++ b/xen/drivers/acpi/pmstat.c Wed Dec 10 13:27:41 2008 +0000
@@ -47,6 +47,11 @@ extern int pmstat_get_cx_stat(uint32_t c
 extern int pmstat_get_cx_stat(uint32_t cpuid, struct pm_cx_stat *stat);
 extern int pmstat_reset_cx_stat(uint32_t cpuid);
 
+extern struct list_head cpufreq_governor_list;
+
+/*
+ * Get PM statistic info
+ */
 int do_get_pm_info(struct xen_sysctl_get_pmstat *op)
 {
     int ret = 0;
@@ -156,3 +161,304 @@ int do_get_pm_info(struct xen_sysctl_get
 
     return ret;
 }
+
+/*
+ * 1. Get PM parameter
+ * 2. Provide user PM control
+ */
+static int read_scaling_available_governors(char *scaling_available_governors,
+                                            unsigned int size)
+{
+    unsigned int i = 0;
+    struct cpufreq_governor *t;
+
+    if ( !scaling_available_governors )
+        return -EINVAL;
+
+    list_for_each_entry(t, &cpufreq_governor_list, governor_list)
+    {
+        i += scnprintf(&scaling_available_governors[i],
+                       CPUFREQ_NAME_LEN, "%s ", t->name);
+        if ( i > size )
+            return -EINVAL;
+    }
+    scaling_available_governors[i-1] = '\0';
+
+    return 0;
+}
+
+static int get_cpufreq_para(struct xen_sysctl_pm_op *op)
+{
+    uint32_t ret = 0;
+    const struct processor_pminfo *pmpt;
+    struct cpufreq_policy *policy;
+    uint32_t gov_num = 0;
+    uint32_t *affected_cpus;
+    uint32_t *scaling_available_frequencies;
+    char     *scaling_available_governors;
+    struct list_head *pos;
+    uint32_t cpu, i, j = 0;
+
+    if ( !op || !cpu_online(op->cpuid) )
+        return -EINVAL;
+    pmpt = processor_pminfo[op->cpuid];
+    policy = cpufreq_cpu_policy[op->cpuid];
+
+    if ( !pmpt || !pmpt->perf.states ||
+         !policy || !policy->governor )
+        return -EINVAL;
+
+    list_for_each(pos, &cpufreq_governor_list)
+        gov_num++;
+
+    if ( (op->get_para.cpu_num  != cpus_weight(policy->cpus)) ||
+         (op->get_para.freq_num != pmpt->perf.state_count)    ||
+         (op->get_para.gov_num  != gov_num) )
+    {
+        op->get_para.cpu_num =  cpus_weight(policy->cpus);
+        op->get_para.freq_num = pmpt->perf.state_count;
+        op->get_para.gov_num  = gov_num;
+        return -EAGAIN;
+    }
+
+    if ( !(affected_cpus = xmalloc_array(uint32_t, op->get_para.cpu_num)) )
+        return -ENOMEM;
+    memset(affected_cpus, 0, op->get_para.cpu_num * sizeof(uint32_t));
+    for_each_cpu_mask(cpu, policy->cpus)
+        affected_cpus[j++] = cpu;
+    ret = copy_to_guest(op->get_para.affected_cpus,
+                       affected_cpus, op->get_para.cpu_num);
+    xfree(affected_cpus);
+    if ( ret )
+        return ret;
+
+    if ( !(scaling_available_frequencies =
+        xmalloc_array(uint32_t, op->get_para.freq_num)) )
+        return -ENOMEM;
+    memset(scaling_available_frequencies, 0,
+           op->get_para.freq_num * sizeof(uint32_t));
+    for ( i = 0; i < op->get_para.freq_num; i++ )
+        scaling_available_frequencies[i] =
+                        pmpt->perf.states[i].core_frequency * 1000;
+    ret = copy_to_guest(op->get_para.scaling_available_frequencies,
+                   scaling_available_frequencies, op->get_para.freq_num);
+    xfree(scaling_available_frequencies);
+    if ( ret )
+        return ret;
+
+    if ( !(scaling_available_governors =
+        xmalloc_array(char, gov_num * CPUFREQ_NAME_LEN)) )
+        return -ENOMEM;
+    memset(scaling_available_governors, 0,
+                gov_num * CPUFREQ_NAME_LEN * sizeof(char));
+    if ( (ret = read_scaling_available_governors(scaling_available_governors,
+                gov_num * CPUFREQ_NAME_LEN * sizeof(char))) )
+    {
+        xfree(scaling_available_governors);
+        return ret;
+    }
+    ret = copy_to_guest(op->get_para.scaling_available_governors,
+                scaling_available_governors, gov_num * CPUFREQ_NAME_LEN);
+    xfree(scaling_available_governors);
+    if ( ret )
+        return ret;
+
+    op->get_para.cpuinfo_cur_freq =
+        cpufreq_driver->get ? cpufreq_driver->get(op->cpuid) : policy->cur;
+    op->get_para.cpuinfo_max_freq = policy->cpuinfo.max_freq;
+    op->get_para.cpuinfo_min_freq = policy->cpuinfo.min_freq;
+    op->get_para.scaling_cur_freq = policy->cur;
+    op->get_para.scaling_max_freq = policy->max;
+    op->get_para.scaling_min_freq = policy->min;
+
+    if ( cpufreq_driver->name )
+        strlcpy(op->get_para.scaling_driver, 
+            cpufreq_driver->name, CPUFREQ_NAME_LEN);
+    else
+        strlcpy(op->get_para.scaling_driver, "Unknown", CPUFREQ_NAME_LEN);
+
+    if ( policy->governor->name )
+        strlcpy(op->get_para.scaling_governor, 
+            policy->governor->name, CPUFREQ_NAME_LEN);
+    else
+        strlcpy(op->get_para.scaling_governor, "Unknown", CPUFREQ_NAME_LEN);
+
+    /* governor specific para */
+    if ( !strnicmp(op->get_para.scaling_governor, 
+                   "userspace", CPUFREQ_NAME_LEN) )
+    {
+        op->get_para.u.userspace.scaling_setspeed = policy->cur;
+    }
+
+    if ( !strnicmp(op->get_para.scaling_governor, 
+                   "ondemand", CPUFREQ_NAME_LEN) )
+    {
+        ret = get_cpufreq_ondemand_para(
+            &op->get_para.u.ondemand.sampling_rate_max,
+            &op->get_para.u.ondemand.sampling_rate_min,
+            &op->get_para.u.ondemand.sampling_rate,
+            &op->get_para.u.ondemand.up_threshold); 
+    }
+
+    return ret;
+}
+
+static int set_cpufreq_gov(struct xen_sysctl_pm_op *op)
+{
+    struct cpufreq_policy new_policy, *old_policy;
+
+    if ( !op || !cpu_online(op->cpuid) )
+        return -EINVAL;
+
+    old_policy = cpufreq_cpu_policy[op->cpuid];
+    if ( !old_policy )
+        return -EINVAL;
+
+    memcpy(&new_policy, old_policy, sizeof(struct cpufreq_policy));
+
+    new_policy.governor = __find_governor(op->set_gov.scaling_governor);
+    if (new_policy.governor == NULL)
+        return -EINVAL;
+
+    return __cpufreq_set_policy(old_policy, &new_policy);
+}
+
+static int set_cpufreq_para(struct xen_sysctl_pm_op *op)
+{
+    int ret = 0;
+    struct cpufreq_policy *policy;
+
+    if ( !op || !cpu_online(op->cpuid) )
+        return -EINVAL;
+    policy = cpufreq_cpu_policy[op->cpuid];
+
+    if ( !policy || !policy->governor )
+        return -EINVAL;
+
+    switch(op->set_para.ctrl_type)
+    {
+    case SCALING_MAX_FREQ:
+    {
+        struct cpufreq_policy new_policy;
+
+        memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
+        new_policy.max = op->set_para.ctrl_value;
+        ret = __cpufreq_set_policy(policy, &new_policy);
+
+        break;
+    }
+
+    case SCALING_MIN_FREQ:
+    {
+        struct cpufreq_policy new_policy;
+
+        memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
+        new_policy.min = op->set_para.ctrl_value;
+        ret = __cpufreq_set_policy(policy, &new_policy);
+
+        break;
+    }
+
+    case SCALING_SETSPEED:
+    {
+        unsigned int freq =op->set_para.ctrl_value;
+
+        if ( !strnicmp(policy->governor->name,
+                       "userspace", CPUFREQ_NAME_LEN) )
+        {
+            if ( freq < policy->min )
+                freq = policy->min;
+            if ( freq > policy->max )
+                freq = policy->max;
+
+            ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
+        }
+        else
+            ret = -EINVAL;
+
+        break;
+    }
+
+    case SAMPLING_RATE:
+    {
+        unsigned int sampling_rate = op->set_para.ctrl_value;
+
+        if ( !strnicmp(policy->governor->name,
+                       "ondemand", CPUFREQ_NAME_LEN) )
+            ret = write_ondemand_sampling_rate(sampling_rate);
+        else
+            ret = -EINVAL;
+
+        break;
+    }
+
+    case UP_THRESHOLD:
+    {
+        unsigned int up_threshold = op->set_para.ctrl_value;
+
+        if ( !strnicmp(policy->governor->name,
+                       "ondemand", CPUFREQ_NAME_LEN) )
+            ret = write_ondemand_up_threshold(up_threshold);
+        else
+            ret = -EINVAL;
+
+        break;
+    }
+
+    default:
+        ret = -EINVAL;
+        break;
+    }
+
+    return ret;
+}
+
+int do_pm_op(struct xen_sysctl_pm_op *op)
+{
+    int ret = 0;
+    const struct processor_pminfo *pmpt;
+
+    if ( !op || !cpu_online(op->cpuid) )
+        return -EINVAL;
+    pmpt = processor_pminfo[op->cpuid];
+
+    switch ( op->cmd & PM_PARA_CATEGORY_MASK )
+    {
+    case CPUFREQ_PARA:
+        if ( !(xen_processor_pmbits & XEN_PROCESSOR_PM_PX) )
+            return -ENODEV;
+        if ( !pmpt || !(pmpt->perf.init & XEN_PX_INIT) )
+            return -EINVAL;
+        break;
+    default:
+        return -ENODEV;
+    }
+
+    switch ( op->cmd )
+    {
+    case GET_CPUFREQ_PARA:
+    {
+        ret = get_cpufreq_para(op);
+        break;
+    }
+
+    case SET_CPUFREQ_GOV:
+    {
+        ret = set_cpufreq_gov(op);
+        break;
+    }
+
+    case SET_CPUFREQ_PARA:
+    {
+        ret = set_cpufreq_para(op);
+        break;
+    }
+
+    default:
+        printk("not defined sub-hypercall @ do_pm_op\n");
+        ret = -ENOSYS;
+        break;
+    }
+
+    return ret;
+}
diff -r 9ba1541d6dc2 -r 605ef79ee46c xen/drivers/cpufreq/cpufreq.c
--- a/xen/drivers/cpufreq/cpufreq.c     Wed Dec 10 13:27:14 2008 +0000
+++ b/xen/drivers/cpufreq/cpufreq.c     Wed Dec 10 13:27:41 2008 +0000
@@ -53,9 +53,9 @@ struct cpufreq_dom {
 };
 static LIST_HEAD(cpufreq_dom_list_head);
 
-static LIST_HEAD(cpufreq_governor_list);
-
-static struct cpufreq_governor *__find_governor(const char *governor)
+LIST_HEAD(cpufreq_governor_list);
+
+struct cpufreq_governor *__find_governor(const char *governor)
 {
     struct cpufreq_governor *t;
 
diff -r 9ba1541d6dc2 -r 605ef79ee46c xen/drivers/cpufreq/cpufreq_ondemand.c
--- a/xen/drivers/cpufreq/cpufreq_ondemand.c    Wed Dec 10 13:27:14 2008 +0000
+++ b/xen/drivers/cpufreq/cpufreq_ondemand.c    Wed Dec 10 13:27:41 2008 +0000
@@ -51,11 +51,49 @@ static struct dbs_tuners {
     unsigned int up_threshold;
     unsigned int powersave_bias;
 } dbs_tuners_ins = {
+    .sampling_rate = 0,
     .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
     .powersave_bias = 0,
 };
 
 static struct timer dbs_timer[NR_CPUS];
+
+int write_ondemand_sampling_rate(unsigned int sampling_rate)
+{
+    if ( (sampling_rate > MAX_SAMPLING_RATE / MICROSECS(1)) ||
+         (sampling_rate < MIN_SAMPLING_RATE / MICROSECS(1)) )
+        return -EINVAL;
+
+    dbs_tuners_ins.sampling_rate = sampling_rate * MICROSECS(1);
+    return 0;
+}
+
+int write_ondemand_up_threshold(unsigned int up_threshold)
+{
+    if ( (up_threshold > MAX_FREQUENCY_UP_THRESHOLD) ||
+         (up_threshold < MIN_FREQUENCY_UP_THRESHOLD) )
+        return -EINVAL;
+
+    dbs_tuners_ins.up_threshold = up_threshold;
+    return 0;
+}
+
+int get_cpufreq_ondemand_para(uint32_t *sampling_rate_max,
+                              uint32_t *sampling_rate_min,
+                              uint32_t *sampling_rate,
+                              uint32_t *up_threshold)
+{
+    if (!sampling_rate_max || !sampling_rate_min ||
+        !sampling_rate || !up_threshold)
+        return -EINVAL;
+
+    *sampling_rate_max = MAX_SAMPLING_RATE/MICROSECS(1);
+    *sampling_rate_min = MIN_SAMPLING_RATE/MICROSECS(1);
+    *sampling_rate = dbs_tuners_ins.sampling_rate / MICROSECS(1);
+    *up_threshold = dbs_tuners_ins.up_threshold;
+
+    return 0;
+}
 
 uint64_t get_cpu_idle_time(unsigned int cpu)
 {
@@ -214,7 +252,7 @@ int cpufreq_governor_dbs(struct cpufreq_
          * Start the timerschedule work, when this governor
          * is used for first time
          */
-        if (dbs_enable == 1) {
+        if ((dbs_enable == 1) && !dbs_tuners_ins.sampling_rate) {
             def_sampling_rate = policy->cpuinfo.transition_latency *
                 DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;
 
diff -r 9ba1541d6dc2 -r 605ef79ee46c xen/include/acpi/cpufreq/cpufreq.h
--- a/xen/include/acpi/cpufreq/cpufreq.h        Wed Dec 10 13:27:14 2008 +0000
+++ b/xen/include/acpi/cpufreq/cpufreq.h        Wed Dec 10 13:27:41 2008 +0000
@@ -16,8 +16,6 @@
 #include <xen/cpumask.h>
 
 #include "processor_perf.h"
-
-#define CPUFREQ_NAME_LEN 16
 
 struct cpufreq_governor;
 
@@ -88,9 +86,14 @@ struct cpufreq_governor {
 };
 
 extern struct cpufreq_governor cpufreq_gov_dbs;
+extern struct cpufreq_governor cpufreq_gov_userspace;
+extern struct cpufreq_governor cpufreq_gov_performance;
+extern struct cpufreq_governor cpufreq_gov_powersave;
+
 extern int cpufreq_register_governor(struct cpufreq_governor *governor);
 extern int cpufreq_unregister_governor(struct cpufreq_governor *governor);
-#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_dbs
+extern struct cpufreq_governor *__find_governor(const char *governor);
+#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_performance
 
 /* pass a target to the cpufreq driver */
 extern int __cpufreq_driver_target(struct cpufreq_policy *policy,
@@ -113,6 +116,7 @@ __cpufreq_governor(struct cpufreq_policy
 #define CPUFREQ_RELATION_H 1  /* highest frequency below or at target */
 
 struct cpufreq_driver {
+    char   name[CPUFREQ_NAME_LEN];
     int    (*init)(struct cpufreq_policy *policy);
     int    (*verify)(struct cpufreq_policy *policy);
     int    (*target)(struct cpufreq_policy *policy,
@@ -210,3 +214,9 @@ struct cpu_dbs_info_s {
 };
 
 int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event);
+int get_cpufreq_ondemand_para(uint32_t *sampling_rate_max,
+                              uint32_t *sampling_rate_min,
+                              uint32_t *sampling_rate,
+                              uint32_t *up_threshold);
+int write_ondemand_sampling_rate(unsigned int sampling_rate);
+int write_ondemand_up_threshold(unsigned int up_threshold);
diff -r 9ba1541d6dc2 -r 605ef79ee46c xen/include/public/sysctl.h
--- a/xen/include/public/sysctl.h       Wed Dec 10 13:27:14 2008 +0000
+++ b/xen/include/public/sysctl.h       Wed Dec 10 13:27:41 2008 +0000
@@ -273,6 +273,91 @@ typedef struct xen_sysctl_cpu_hotplug xe
 typedef struct xen_sysctl_cpu_hotplug xen_sysctl_cpu_hotplug_t;
 DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpu_hotplug_t);
 
+/*
+ * Get/set xen power management, include 
+ * 1. cpufreq governors and related parameters
+ */
+#define XEN_SYSCTL_pm_op        12
+struct xen_userspace {
+    uint32_t scaling_setspeed;
+};
+typedef struct xen_userspace xen_userspace_t;
+
+struct xen_ondemand {
+    uint32_t sampling_rate_max;
+    uint32_t sampling_rate_min;
+
+    uint32_t sampling_rate;
+    uint32_t up_threshold;
+};
+typedef struct xen_ondemand xen_ondemand_t;
+
+/* 
+ * cpufreq para name of this structure named 
+ * same as sysfs file name of native linux
+ */
+#define CPUFREQ_NAME_LEN 16
+struct xen_get_cpufreq_para {
+    /* IN/OUT variable */
+    uint32_t cpu_num;
+    uint32_t freq_num;
+    uint32_t gov_num;
+
+    /* for all governors */
+    /* OUT variable */
+    XEN_GUEST_HANDLE_64(uint32) affected_cpus;
+    XEN_GUEST_HANDLE_64(uint32) scaling_available_frequencies;
+    XEN_GUEST_HANDLE_64(char)   scaling_available_governors;
+    char scaling_driver[CPUFREQ_NAME_LEN];
+
+    uint32_t cpuinfo_cur_freq;
+    uint32_t cpuinfo_max_freq;
+    uint32_t cpuinfo_min_freq;
+    uint32_t scaling_cur_freq;
+
+    char scaling_governor[CPUFREQ_NAME_LEN];
+    uint32_t scaling_max_freq;
+    uint32_t scaling_min_freq;
+
+    /* for specific governor */
+    union {
+        struct  xen_userspace userspace;
+        struct  xen_ondemand ondemand;
+    } u;
+};
+
+struct xen_set_cpufreq_gov {
+    char scaling_governor[CPUFREQ_NAME_LEN];
+};
+
+struct xen_set_cpufreq_para {
+    #define SCALING_MAX_FREQ           1
+    #define SCALING_MIN_FREQ           2
+    #define SCALING_SETSPEED           3
+    #define SAMPLING_RATE              4
+    #define UP_THRESHOLD               5
+
+    uint32_t ctrl_type;
+    uint32_t ctrl_value;
+};
+
+struct xen_sysctl_pm_op {
+    #define PM_PARA_CATEGORY_MASK      0xf0
+    #define CPUFREQ_PARA               0x10
+
+    /* cpufreq command type */
+    #define GET_CPUFREQ_PARA           (CPUFREQ_PARA | 0x01)
+    #define SET_CPUFREQ_GOV            (CPUFREQ_PARA | 0x02)
+    #define SET_CPUFREQ_PARA           (CPUFREQ_PARA | 0x03)
+
+    uint32_t cmd;
+    uint32_t cpuid;
+    union {
+        struct xen_get_cpufreq_para get_para;
+        struct xen_set_cpufreq_gov  set_gov;
+        struct xen_set_cpufreq_para set_para;
+    };
+};
 
 struct xen_sysctl {
     uint32_t cmd;
@@ -289,6 +374,7 @@ struct xen_sysctl {
         struct xen_sysctl_availheap         availheap;
         struct xen_sysctl_get_pmstat        get_pmstat;
         struct xen_sysctl_cpu_hotplug       cpu_hotplug;
+        struct xen_sysctl_pm_op             pm_op;
         uint8_t                             pad[128];
     } u;
 };

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.