WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

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

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Add user PM control interface
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 16 Dec 2008 22:30:17 -0800
Delivery-date: Tue, 16 Dec 2008 22:30:15 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] Add user PM control interface, Xen patchbot-unstable <=