From mboxrd@z Thu Jan 1 00:00:00 1970 From: Wei Wang Subject: [PATCH v4 10/11] x86/intel_pstate: support the use of intel_pstate in pmstat.c Date: Thu, 25 Jun 2015 19:17:13 +0800 Message-ID: <1435231033-22806-1-git-send-email-wei.w.wang@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: jbeulich@suse.com, andrew.cooper3@citrix.com, xen-devel@lists.xen.org Cc: Wei Wang List-Id: xen-devel@lists.xenproject.org Add support in the pmstat.c so that the xenpm tool can request to access the intel_pstate driver. v4 changes: 1) changed to use the "internal_governor struct"; 2) coding style change (indentation of "gov_num++"). Signed-off-by: Wei Wang --- tools/libxc/xc_pm.c | 4 +- xen/drivers/acpi/pmstat.c | 148 ++++++++++++++++++++++++++++++++++++-------- xen/include/public/sysctl.h | 16 ++++- 3 files changed, 138 insertions(+), 30 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..89628aa 100644 --- a/xen/drivers/acpi/pmstat.c +++ b/xen/drivers/acpi/pmstat.c @@ -192,22 +192,33 @@ 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; + struct internal_governor *internal_gov; 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; + uint32_t cur_gov; 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) || @@ -241,28 +252,47 @@ 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) { + scaling_available_governors = internal_gov->avail_gov; + ret = copy_to_guest(op->u.get_para.scaling_available_governors, + scaling_available_governors, 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.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 (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, @@ -300,16 +350,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); } @@ -318,10 +388,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) @@ -348,6 +420,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/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