[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v6 5/6] 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> --- changes in v6: 1) add the NON_INTERNAL_GOV macro to replace literal 0; 2) code consolidation (e.g. merging some code into if/else, as required in v5); 3) somewhere, change to use clamp, instead of clamp_t; 4) xen_perf_alias, instead of perf_alias. tools/libxc/include/xenctrl.h | 20 ++-- tools/libxc/xc_pm.c | 16 ++-- tools/misc/xenpm.c | 4 +- xen/drivers/acpi/pmstat.c | 183 +++++++++++++++++++++++++++++++------ xen/include/acpi/cpufreq/cpufreq.h | 2 + xen/include/public/sysctl.h | 29 ++++-- 6 files changed, 198 insertions(+), 56 deletions(-) diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index 3bfa00b..590eb72 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -2270,6 +2270,17 @@ struct xc_get_cpufreq_para { 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 xen_perf_alias perf_alias; /* for all governors */ /* OUT variable */ @@ -2278,22 +2289,13 @@ struct xc_get_cpufreq_para { 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; - - int32_t turbo_enabled; }; int xc_get_cpufreq_para(xc_interface *xch, int cpuid, diff --git a/tools/libxc/xc_pm.c b/tools/libxc/xc_pm.c index 5b38cf1..6a16e8a 100644 --- a/tools/libxc/xc_pm.c +++ b/tools/libxc/xc_pm.c @@ -260,13 +260,15 @@ 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_perf = sys_para->scaling_max_perf; + user_para->scaling_min_perf = sys_para->scaling_min_perf; + user_para->scaling_turbo_pct = sys_para->scaling_turbo_pct; + user_para->perf_alias = sys_para->perf_alias; + user_para->turbo_enabled = sys_para->turbo_enabled; memcpy(user_para->scaling_driver, sys_para->scaling_driver, CPUFREQ_NAME_LEN); diff --git a/tools/misc/xenpm.c b/tools/misc/xenpm.c index 08f2242..5944fdb 100644 --- a/tools/misc/xenpm.c +++ b/tools/misc/xenpm.c @@ -705,8 +705,8 @@ static void print_cpufreq_para(int cpuid, struct xc_get_cpufreq_para *p_cpufreq) printf("\n"); printf("scaling frequency : max [%u] min [%u] cur [%u]\n", - p_cpufreq->scaling_max_freq, - p_cpufreq->scaling_min_freq, + p_cpufreq->scaling_max_perf, + p_cpufreq->scaling_min_perf, p_cpufreq->scaling_cur_freq); printf("turbo mode : %s\n", diff --git a/xen/drivers/acpi/pmstat.c b/xen/drivers/acpi/pmstat.c index 892260d..7825f91 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,24 @@ 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; if ( !pmpt || !pmpt->perf.states || - !policy || !policy->governor ) + !policy || (!policy->governor && !internal_gov) ) return -EINVAL; - list_for_each(pos, &cpufreq_governor_list) - gov_num++; + if ( internal_gov ) + { + cur_gov = internal_gov->cur_gov; + gov_num = internal_gov->gov_num; + } + else + { + cur_gov = NON_INTERNAL_GOV; + 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 +253,85 @@ 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; + 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 + { + op->u.get_para.scaling_max_perf = policy->max; + op->u.get_para.scaling_min_perf = policy->min; + op->u.get_para.perf_alias = FREQUENCY; + } if ( cpufreq_driver->name[0] ) - strlcpy(op->u.get_para.scaling_driver, + strlcpy(op->u.get_para.scaling_driver, cpufreq_driver->name, CPUFREQ_NAME_LEN); 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; + case NON_INTERNAL_GOV: + 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,45 @@ 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(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(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 +485,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 +501,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/acpi/cpufreq/cpufreq.h b/xen/include/acpi/cpufreq/cpufreq.h index ef6643a..5cbe71e 100644 --- a/xen/include/acpi/cpufreq/cpufreq.h +++ b/xen/include/acpi/cpufreq/cpufreq.h @@ -107,7 +107,9 @@ struct cpufreq_freqs { * CPUFREQ GOVERNORS * *********************************************************************/ + /* Please add internal governors here */ +#define NON_INTERNAL_GOV (0) #define INTERNAL_GOV_POWERSAVE (1) #define INTERNAL_GOV_PERFORMANCE (2) #define INTERNAL_GOV_USERSPACE (3) diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index 96680eb..dcfe541 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 xen_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 xen_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 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |