From: Wei Wang <wei.w.wang@intel.com>
To: jbeulich@suse.com, andrew.cooper3@citrix.com, xen-devel@lists.xen.org
Cc: Wei Wang <wei.w.wang@intel.com>
Subject: [PATCH v5 8/9] x86/intel_pstate: support the use of intel_pstate in pmstat.c
Date: Mon, 14 Sep 2015 10:32:09 +0800 [thread overview]
Message-ID: <1442197930-3738-9-git-send-email-wei.w.wang@intel.com> (raw)
In-Reply-To: <1442197930-3738-1-git-send-email-wei.w.wang@intel.com>
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@intel.com>
---
tools/libxc/xc_pm.c | 15 ++--
xen/drivers/acpi/pmstat.c | 179 +++++++++++++++++++++++++++++++++++++-------
xen/include/public/sysctl.h | 29 ++++---
3 files changed, 179 insertions(+), 44 deletions(-)
changes in v5:
1) remove a intermediate variable, "scaling_avail_governors";
2) add condition checks in set_cpufreq_para();
3) replace the previous union "scaling_max" and "scaling_min" with
"uint32_t scaling_max_perf" and "uint32_t scaling_min_perf";
4) add "enum perf_alias", to indicate the meaning of "scaling_max_perf"
and "scaling_min_perf" - holding Percentage values or Frequency values;
5) re-organize the xen_get_cpufreq_para structure to make it less than
128Byte;
6) coding style changes.
diff --git a/tools/libxc/xc_pm.c b/tools/libxc/xc_pm.c
index 5b38cf1..5ad777a 100644
--- a/tools/libxc/xc_pm.c
+++ b/tools/libxc/xc_pm.c
@@ -260,13 +260,14 @@ int xc_get_cpufreq_para(xc_interface *xch, int cpuid,
}
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;
- user_para->turbo_enabled = sys_para->turbo_enabled;
+ 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.pct = sys_para->scaling_max_perf;
+ user_para->scaling_min.pct = sys_para->scaling_min_perf;
+ user_para->scaling_turbo_pct = sys_para->scaling_turbo_pct;
+ user_para->turbo_enabled = sys_para->turbo_enabled;
memcpy(user_para->scaling_driver,
sys_para->scaling_driver, CPUFREQ_NAME_LEN);
diff --git a/xen/drivers/acpi/pmstat.c b/xen/drivers/acpi/pmstat.c
index 892260d..97893c5 100644
--- a/xen/drivers/acpi/pmstat.c
+++ b/xen/drivers/acpi/pmstat.c
@@ -191,7 +191,9 @@ 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;
+ struct perf_limits *limits;
+ struct internal_governor *internal_gov;
+ uint32_t cur_gov, gov_num = 0;
uint32_t *affected_cpus;
uint32_t *scaling_available_frequencies;
char *scaling_available_governors;
@@ -200,13 +202,21 @@ 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;
+ internal_gov = policy->internal_gov;
+ cur_gov = internal_gov ? internal_gov->cur_gov : 0;
if ( !pmpt || !pmpt->perf.states ||
- !policy || !policy->governor )
+ !policy || (!policy->governor && !policy->internal_gov) )
return -EINVAL;
- list_for_each(pos, &cpufreq_governor_list)
- gov_num++;
+ if ( internal_gov )
+ gov_num = internal_gov->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) ||
@@ -240,40 +250,88 @@ static int get_cpufreq_para(struct xen_sysctl_pm_op *op)
if ( ret )
return ret;
- if ( !(scaling_available_governors =
- 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))) )
+ if ( internal_gov )
{
+ ret = copy_to_guest(op->u.get_para.scaling_available_governors,
+ internal_gov->avail_gov, gov_num * CPUFREQ_NAME_LEN);
+ if ( ret )
+ return ret;
+ }
+ else
+ {
+ if ( !(scaling_available_governors =
+ 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))) )
+ {
+ xfree(scaling_available_governors);
+ return ret;
+ }
+ ret = copy_to_guest(op->u.get_para.scaling_available_governors,
+ scaling_available_governors, gov_num * CPUFREQ_NAME_LEN);
xfree(scaling_available_governors);
- return ret;
+ if ( ret )
+ return ret;
}
- ret = copy_to_guest(op->u.get_para.scaling_available_governors,
- scaling_available_governors, gov_num * CPUFREQ_NAME_LEN);
- xfree(scaling_available_governors);
- if ( ret )
- return ret;
-
op->u.get_para.cpuinfo_cur_freq =
cpufreq_driver->get ? cpufreq_driver->get(op->cpuid) : policy->cur;
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 ( internal_gov )
+ {
+ op->u.get_para.scaling_max_perf = limits->max_perf_pct;
+ op->u.get_para.scaling_min_perf = limits->min_perf_pct;
+ op->u.get_para.scaling_turbo_pct = limits->turbo_pct;
+ }
+ else
+ {
+ op->u.get_para.scaling_max_perf = policy->max;
+ op->u.get_para.scaling_min_perf = policy->min;
+ }
if ( cpufreq_driver->name[0] )
+ {
strlcpy(op->u.get_para.scaling_driver,
cpufreq_driver->name, CPUFREQ_NAME_LEN);
+ if ( !strncmp(cpufreq_driver->name,
+ "intel_pstate", CPUFREQ_NAME_LEN) )
+ op->u.get_para.perf_alias = PERCENTAGE;
+ else
+ op->u.get_para.perf_alias = FREQUENCY;
+ }
else
+ {
strlcpy(op->u.get_para.scaling_driver, "Unknown", CPUFREQ_NAME_LEN);
+ op->u.get_para.perf_alias = FREQUENCY;
+ }
- 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 ( cur_gov )
+ {
+ case INTERNAL_GOV_PERFORMANCE:
+ strlcpy(op->u.get_para.scaling_governor,
+ "performance", CPUFREQ_NAME_LEN);
+ break;
+ case INTERNAL_GOV_POWERSAVE:
+ strlcpy(op->u.get_para.scaling_governor,
+ "powersave", CPUFREQ_NAME_LEN);
+ break;
+ case INTERNAL_GOV_USERSPACE:
+ strlcpy(op->u.get_para.scaling_governor,
+ "userspace", CPUFREQ_NAME_LEN);
+ break;
+ case INTERNAL_GOV_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,
@@ -299,16 +357,36 @@ static int get_cpufreq_para(struct xen_sysctl_pm_op *op)
static int set_cpufreq_gov(struct xen_sysctl_pm_op *op)
{
struct cpufreq_policy new_policy, *old_policy;
+ struct internal_governor *internal_gov;
old_policy = per_cpu(cpufreq_cpu_policy, op->cpuid);
if ( !old_policy )
return -EINVAL;
+ internal_gov = old_policy->internal_gov;
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 ( internal_gov && internal_gov->cur_gov )
+ {
+ if ( !strnicmp(op->u.set_gov.scaling_governor,
+ "performance", CPUFREQ_NAME_LEN) )
+ internal_gov->cur_gov = INTERNAL_GOV_PERFORMANCE;
+ else if ( !strnicmp(op->u.set_gov.scaling_governor,
+ "powersave", CPUFREQ_NAME_LEN) )
+ internal_gov->cur_gov = INTERNAL_GOV_POWERSAVE;
+ else if ( !strnicmp(op->u.set_gov.scaling_governor,
+ "userspace", CPUFREQ_NAME_LEN) )
+ internal_gov->cur_gov = INTERNAL_GOV_USERSPACE;
+ else if ( !strnicmp(op->u.set_gov.scaling_governor,
+ "ondemand", CPUFREQ_NAME_LEN) )
+ internal_gov->cur_gov = INTERNAL_GOV_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);
}
@@ -317,10 +395,12 @@ static int set_cpufreq_para(struct xen_sysctl_pm_op *op)
{
int ret = 0;
struct cpufreq_policy *policy;
+ struct internal_governor *internal_gov;
policy = per_cpu(cpufreq_cpu_policy, op->cpuid);
+ internal_gov = policy->internal_gov;
- if ( !policy || !policy->governor )
+ if ( !policy || (!policy->governor && !internal_gov) )
return -EINVAL;
switch(op->u.set_para.ctrl_type)
@@ -329,6 +409,9 @@ static int set_cpufreq_para(struct xen_sysctl_pm_op *op)
{
struct cpufreq_policy new_policy;
+ if ( !policy->governor || internal_gov )
+ return -EINVAL;
+
memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
new_policy.max = op->u.set_para.ctrl_value;
ret = __cpufreq_set_policy(policy, &new_policy);
@@ -340,6 +423,9 @@ static int set_cpufreq_para(struct xen_sysctl_pm_op *op)
{
struct cpufreq_policy new_policy;
+ if ( !policy->governor || internal_gov )
+ return -EINVAL;
+
memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
new_policy.min = op->u.set_para.ctrl_value;
ret = __cpufreq_set_policy(policy, &new_policy);
@@ -347,10 +433,43 @@ 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;
+
+ if ( policy->governor || !internal_gov )
+ return -EINVAL;
+
+ 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;
+
+ if ( policy->governor || !internal_gov )
+ return -EINVAL;
+
+ 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;
+ if ( !policy->governor || internal_gov )
+ return -EINVAL;
+
if ( !strnicmp(policy->governor->name,
"userspace", CPUFREQ_NAME_LEN) )
ret = write_userspace_scaling_setspeed(op->cpuid, freq);
@@ -364,6 +483,9 @@ static int set_cpufreq_para(struct xen_sysctl_pm_op *op)
{
unsigned int sampling_rate = op->u.set_para.ctrl_value;
+ if ( !policy->governor || internal_gov )
+ return -EINVAL;
+
if ( !strnicmp(policy->governor->name,
"ondemand", CPUFREQ_NAME_LEN) )
ret = write_ondemand_sampling_rate(sampling_rate);
@@ -377,6 +499,9 @@ static int set_cpufreq_para(struct xen_sysctl_pm_op *op)
{
unsigned int up_threshold = op->u.set_para.ctrl_value;
+ if ( !policy->governor || internal_gov )
+ return -EINVAL;
+
if ( !strnicmp(policy->governor->name,
"ondemand", CPUFREQ_NAME_LEN) )
ret = write_ondemand_up_threshold(up_threshold);
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index 0cacacc..6d39fe9 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -297,11 +297,28 @@ typedef struct xen_ondemand xen_ondemand_t;
* same as sysfs file name of native linux
*/
#define CPUFREQ_NAME_LEN 16
+
+enum perf_alias {
+ FREQUENCY = 0,
+ PERCENTAGE = 1
+};
+
struct xen_get_cpufreq_para {
/* IN/OUT variable */
uint32_t cpu_num;
uint32_t freq_num;
uint32_t gov_num;
+ int32_t turbo_enabled;
+
+ uint32_t cpuinfo_cur_freq;
+ uint32_t cpuinfo_max_freq;
+ uint32_t cpuinfo_min_freq;
+ uint32_t scaling_cur_freq;
+
+ uint32_t scaling_turbo_pct;
+ uint32_t scaling_max_perf;
+ uint32_t scaling_min_perf;
+ enum perf_alias perf_alias;
/* for all governors */
/* OUT variable */
@@ -309,23 +326,13 @@ struct xen_get_cpufreq_para {
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;
-
- int32_t turbo_enabled;
};
struct xen_set_cpufreq_gov {
@@ -338,6 +345,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
next prev parent reply other threads:[~2015-09-14 2:32 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-14 2:32 [PATCH v5 0/9] Porting the intel_pstate driver to Xen Wei Wang
2015-09-14 2:32 ` [PATCH v5 1/9] x86/intel_pstate: add some calculation related support Wei Wang
2015-09-17 15:19 ` Andrew Cooper
2015-10-05 16:00 ` Jan Beulich
2015-09-14 2:32 ` [PATCH v5 2/9] x86/intel_pstate: APERF/MPERF feature detect Wei Wang
2015-09-17 15:26 ` Andrew Cooper
2015-10-05 16:14 ` Jan Beulich
2015-09-14 2:32 ` [PATCH v5 3/9] x86/intel_pstate: add a new driver interface, setpolicy() Wei Wang
2015-09-17 15:34 ` Andrew Cooper
2015-10-06 15:37 ` Jan Beulich
2015-09-14 2:32 ` [PATCH v5 4/9] x86/intel_pstate: relocate the driver register function Wei Wang
2015-09-17 15:38 ` Andrew Cooper
2015-09-21 13:13 ` Jan Beulich
2015-10-07 15:08 ` Jan Beulich
2015-09-14 2:32 ` [PATCH v5 5/9] x86/intel_pstate: changes in cpufreq_del_cpu for CPU offline Wei Wang
2015-09-17 15:43 ` Andrew Cooper
2015-10-07 15:28 ` Jan Beulich
2015-10-11 2:19 ` Wang, Wei W
2015-09-14 2:32 ` [PATCH v5 6/9] x86/intel_pstate: the main boby of the intel_pstate driver Wei Wang
2015-09-17 15:51 ` Andrew Cooper
2015-10-07 15:39 ` Jan Beulich
2015-09-14 2:32 ` [PATCH v5 7/9] x86/intel_pstate: add a booting param to select the driver to load Wei Wang
2015-09-17 16:08 ` Andrew Cooper
2015-09-21 13:15 ` Jan Beulich
2015-10-07 15:46 ` Jan Beulich
2015-10-23 8:09 ` Wang, Wei W
2015-10-23 8:16 ` Wang, Wei W
2015-10-23 8:18 ` Wang, Wei W
2015-10-23 8:35 ` Jan Beulich
2015-10-23 8:48 ` Wang, Wei W
2015-09-14 2:32 ` Wei Wang [this message]
2015-10-07 16:10 ` [PATCH v5 8/9] x86/intel_pstate: support the use of intel_pstate in pmstat.c Jan Beulich
2015-10-26 6:26 ` Wang, Wei W
2015-10-26 7:02 ` Jan Beulich
2015-10-26 7:59 ` Wang, Wei W
2015-10-26 9:40 ` Jan Beulich
2015-10-26 9:48 ` Wang, Wei W
2015-10-26 9:53 ` Jan Beulich
2015-10-26 10:19 ` Wang, Wei W
2015-10-26 10:35 ` Jan Beulich
2015-10-26 10:45 ` Wang, Wei W
2015-10-26 10:51 ` Jan Beulich
2015-10-26 11:03 ` Wang, Wei W
2015-09-14 2:32 ` [PATCH v5 9/9] tools: enable xenpm to control the intel_pstate driver Wei Wang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1442197930-3738-9-git-send-email-wei.w.wang@intel.com \
--to=wei.w.wang@intel.com \
--cc=andrew.cooper3@citrix.com \
--cc=jbeulich@suse.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).