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

[Xen-devel] [PATCH v3 10/11] x86/intel_pstate: support the use of intel_pstate in pmstat.c



Add support in the pmstat.c so that the xenpm tool can request to
access the intel_pstate driver.

Signed-off-by: Wei Wang <wei.w.wang@xxxxxxxxx>
---
 tools/libxc/xc_pm.c                |   4 +-
 xen/drivers/acpi/pmstat.c          | 130 +++++++++++++++++++++++++++++++------
 xen/include/acpi/cpufreq/cpufreq.h |   2 +
 xen/include/public/sysctl.h        |  16 ++++-
 4 files changed, 129 insertions(+), 23 deletions(-)

diff --git a/tools/libxc/xc_pm.c b/tools/libxc/xc_pm.c
index 5a7148e..823bab6 100644
--- a/tools/libxc/xc_pm.c
+++ b/tools/libxc/xc_pm.c
@@ -265,8 +265,8 @@ int xc_get_cpufreq_para(xc_interface *xch, int cpuid,
         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;
+        user_para->scaling_max_freq = sys_para->scaling_max.freq;
+        user_para->scaling_min_freq = sys_para->scaling_min.freq;
         user_para->turbo_enabled    = sys_para->turbo_enabled;
 
         memcpy(user_para->scaling_driver,
diff --git a/xen/drivers/acpi/pmstat.c b/xen/drivers/acpi/pmstat.c
index daac2da..53d811f 100644
--- a/xen/drivers/acpi/pmstat.c
+++ b/xen/drivers/acpi/pmstat.c
@@ -167,7 +167,7 @@ int do_get_pm_info(struct xen_sysctl_get_pmstat *op)
  * 2. Provide user PM control
  */
 static int read_scaling_available_governors(char *scaling_available_governors,
-                                            unsigned int size)
+                                            unsigned int size, bool_t internal)
 {
     unsigned int i = 0;
     struct cpufreq_governor *t;
@@ -175,12 +175,26 @@ static int read_scaling_available_governors(char 
*scaling_available_governors,
     if ( !scaling_available_governors )
         return -EINVAL;
 
-    list_for_each_entry(t, &cpufreq_governor_list, governor_list)
+    if (internal)
     {
+        i += scnprintf(&scaling_available_governors[0],
+                               CPUFREQ_NAME_LEN, "%s ", "performance");
         i += scnprintf(&scaling_available_governors[i],
-                       CPUFREQ_NAME_LEN, "%s ", t->name);
-        if ( i > size )
-            return -EINVAL;
+                               CPUFREQ_NAME_LEN, "%s ", "powersave");
+        i += scnprintf(&scaling_available_governors[i],
+                               CPUFREQ_NAME_LEN, "%s ", "userspace");
+        i += scnprintf(&scaling_available_governors[i],
+                               CPUFREQ_NAME_LEN, "%s ", "ondemand");
+    }
+    else
+    {
+        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';
 
@@ -192,6 +206,7 @@ static int get_cpufreq_para(struct xen_sysctl_pm_op *op)
     uint32_t ret = 0;
     const struct processor_pminfo *pmpt;
     struct cpufreq_policy *policy;
+    struct perf_limits *limits;
     uint32_t gov_num = 0;
     uint32_t *affected_cpus;
     uint32_t *scaling_available_frequencies;
@@ -201,13 +216,19 @@ static int get_cpufreq_para(struct xen_sysctl_pm_op *op)
 
     pmpt = processor_pminfo[op->cpuid];
     policy = per_cpu(cpufreq_cpu_policy, op->cpuid);
+    limits = &policy->limits;
 
     if ( !pmpt || !pmpt->perf.states ||
-         !policy || !policy->governor )
+         !policy || (!policy->governor && !policy->policy) )
         return -EINVAL;
 
-    list_for_each(pos, &cpufreq_governor_list)
+    if (policy->policy)
+        gov_num = INTEL_PSTATE_INTERNAL_GOV_NUM;
+    else
+    {
+        list_for_each(pos, &cpufreq_governor_list)
         gov_num++;
+    }
 
     if ( (op->u.get_para.cpu_num  != cpumask_weight(policy->cpus)) ||
          (op->u.get_para.freq_num != pmpt->perf.state_count)    ||
@@ -245,7 +266,7 @@ static int get_cpufreq_para(struct xen_sysctl_pm_op *op)
            xzalloc_array(char, gov_num * CPUFREQ_NAME_LEN)) )
         return -ENOMEM;
     if ( (ret = read_scaling_available_governors(scaling_available_governors,
-                gov_num * CPUFREQ_NAME_LEN * sizeof(char))) )
+                gov_num * CPUFREQ_NAME_LEN * sizeof(char), !!policy->policy)) )
     {
         xfree(scaling_available_governors);
         return ret;
@@ -261,8 +282,17 @@ static int get_cpufreq_para(struct xen_sysctl_pm_op *op)
     op->u.get_para.cpuinfo_max_freq = policy->cpuinfo.max_freq;
     op->u.get_para.cpuinfo_min_freq = policy->cpuinfo.min_freq;
     op->u.get_para.scaling_cur_freq = policy->cur;
-    op->u.get_para.scaling_max_freq = policy->max;
-    op->u.get_para.scaling_min_freq = policy->min;
+    if (policy->policy)
+    {
+        op->u.get_para.scaling_max.pct = limits->max_perf_pct;
+        op->u.get_para.scaling_min.pct = limits->min_perf_pct;
+        op->u.get_para.scaling_turbo_pct = limits->turbo_pct;
+    }
+    else
+    {
+        op->u.get_para.scaling_max.freq = policy->max;
+        op->u.get_para.scaling_min.freq = policy->min;
+    }
 
     if ( cpufreq_driver->name[0] )
         strlcpy(op->u.get_para.scaling_driver, 
@@ -270,11 +300,31 @@ static int get_cpufreq_para(struct xen_sysctl_pm_op *op)
     else
         strlcpy(op->u.get_para.scaling_driver, "Unknown", CPUFREQ_NAME_LEN);
 
-    if ( policy->governor->name[0] )
-        strlcpy(op->u.get_para.scaling_governor, 
-            policy->governor->name, CPUFREQ_NAME_LEN);
-    else
-        strlcpy(op->u.get_para.scaling_governor, "Unknown", CPUFREQ_NAME_LEN);
+    switch (policy->policy)
+    {
+    case CPUFREQ_POLICY_PERFORMANCE:
+        strlcpy(op->u.get_para.scaling_governor,
+            "performance", CPUFREQ_NAME_LEN);
+        break;
+    case CPUFREQ_POLICY_POWERSAVE:
+        strlcpy(op->u.get_para.scaling_governor,
+            "powersave", CPUFREQ_NAME_LEN);
+        break;
+    case CPUFREQ_POLICY_USERSPACE:
+        strlcpy(op->u.get_para.scaling_governor,
+            "userspace", CPUFREQ_NAME_LEN);
+        break;
+    case CPUFREQ_POLICY_ONDEMAND:
+        strlcpy(op->u.get_para.scaling_governor,
+            "ondemand", CPUFREQ_NAME_LEN);
+        break;
+    default:
+        if ( policy->governor->name[0] )
+            strlcpy(op->u.get_para.scaling_governor,
+                policy->governor->name, CPUFREQ_NAME_LEN);
+        else
+            strlcpy(op->u.get_para.scaling_governor, "Unknown", 
CPUFREQ_NAME_LEN);
+    }
 
     /* governor specific para */
     if ( !strnicmp(op->u.get_para.scaling_governor, 
@@ -307,9 +357,27 @@ static int set_cpufreq_gov(struct xen_sysctl_pm_op *op)
 
     memcpy(&new_policy, old_policy, sizeof(struct cpufreq_policy));
 
-    new_policy.governor = __find_governor(op->u.set_gov.scaling_governor);
-    if (new_policy.governor == NULL)
-        return -EINVAL;
+    if (old_policy->policy)
+    {
+        if ( !strnicmp(op->u.set_gov.scaling_governor,
+                       "performance", CPUFREQ_NAME_LEN) )
+            old_policy->policy = CPUFREQ_POLICY_PERFORMANCE;
+        else if ( !strnicmp(op->u.set_gov.scaling_governor,
+                       "powersave", CPUFREQ_NAME_LEN) )
+            old_policy->policy = CPUFREQ_POLICY_POWERSAVE;
+        else if ( !strnicmp(op->u.set_gov.scaling_governor,
+                       "userspace", CPUFREQ_NAME_LEN) )
+            old_policy->policy = CPUFREQ_POLICY_USERSPACE;
+        else if ( !strnicmp(op->u.set_gov.scaling_governor,
+                       "ondemand", CPUFREQ_NAME_LEN) )
+            old_policy->policy = CPUFREQ_POLICY_ONDEMAND;
+    }
+    else
+    {
+        new_policy.governor = __find_governor(op->u.set_gov.scaling_governor);
+        if (new_policy.governor == NULL)
+            return -EINVAL;
+    }
 
     return __cpufreq_set_policy(old_policy, &new_policy);
 }
@@ -321,7 +389,7 @@ static int set_cpufreq_para(struct xen_sysctl_pm_op *op)
 
     policy = per_cpu(cpufreq_cpu_policy, op->cpuid);
 
-    if ( !policy || !policy->governor )
+    if ( !policy || (!policy->governor && !policy->policy) )
         return -EINVAL;
 
     switch(op->u.set_para.ctrl_type)
@@ -348,6 +416,30 @@ static int set_cpufreq_para(struct xen_sysctl_pm_op *op)
         break;
     }
 
+    case SCALING_MAX_PCT:
+    {
+        struct cpufreq_policy new_policy;
+        struct perf_limits *limits = &new_policy.limits;
+
+        new_policy = *policy;
+        limits->max_perf_pct = clamp_t(uint32_t, op->u.set_para.ctrl_value,
+                       limits->min_policy_pct, limits->max_policy_pct);
+        ret = __cpufreq_set_policy(policy, &new_policy);
+        break;
+    }
+
+    case SCALING_MIN_PCT:
+    {
+        struct cpufreq_policy new_policy;
+        struct perf_limits *limits = &new_policy.limits;
+
+        new_policy = *policy;
+        limits->min_perf_pct = clamp_t(uint32_t, op->u.set_para.ctrl_value,
+                       limits->min_policy_pct, limits->max_policy_pct);
+        ret = __cpufreq_set_policy(policy, &new_policy);
+        break;
+    }
+
     case SCALING_SETSPEED:
     {
         unsigned int freq =op->u.set_para.ctrl_value;
diff --git a/xen/include/acpi/cpufreq/cpufreq.h 
b/xen/include/acpi/cpufreq/cpufreq.h
index 71bb45c..e8a6bab 100644
--- a/xen/include/acpi/cpufreq/cpufreq.h
+++ b/xen/include/acpi/cpufreq/cpufreq.h
@@ -109,6 +109,8 @@ struct cpufreq_freqs {
  *                          CPUFREQ GOVERNORS                        *
  *********************************************************************/
 
+#define INTEL_PSTATE_INTERNAL_GOV_NUM 4
+
 /* The four internal governors used in intel_pstate */
 #define CPUFREQ_POLICY_POWERSAVE        (1)
 #define CPUFREQ_POLICY_PERFORMANCE      (2)
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index 0cf9277..1bb730c 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -315,8 +315,18 @@ struct xen_get_cpufreq_para {
     uint32_t scaling_cur_freq;
 
     char scaling_governor[CPUFREQ_NAME_LEN];
-    uint32_t scaling_max_freq;
-    uint32_t scaling_min_freq;
+
+    union {
+        uint32_t freq;
+        uint32_t pct;
+    } scaling_max;
+
+    union {
+        uint32_t freq;
+        uint32_t pct;
+    } scaling_min;
+
+    uint32_t scaling_turbo_pct;
 
     /* for specific governor */
     union {
@@ -337,6 +347,8 @@ struct xen_set_cpufreq_para {
     #define SCALING_SETSPEED           3
     #define SAMPLING_RATE              4
     #define UP_THRESHOLD               5
+    #define SCALING_MAX_PCT            6
+    #define SCALING_MIN_PCT            7
 
     uint32_t ctrl_type;
     uint32_t ctrl_value;
-- 
1.9.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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