diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2010-02-08 08:48:40 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2010-02-08 08:48:40 +0000 |
commit | d2a92c94a1b314750a94b902e9584200b2b507b0 (patch) | |
tree | 9b52b5ef5f93725be81e517586f08d57a8a81f31 | |
parent | 43d6e1096b0df2b2ba0780fa41b525e11518e520 (diff) | |
download | xen-d2a92c94a1b314750a94b902e9584200b2b507b0.tar.gz xen-d2a92c94a1b314750a94b902e9584200b2b507b0.tar.bz2 xen-d2a92c94a1b314750a94b902e9584200b2b507b0.zip |
xenpm: Allow user to enable/disable dbs governor turbo mode.
Signed-off-by: Lu Guanqun <guanqun.lu@intel.com>
-rw-r--r-- | tools/libxc/xc_pm.c | 25 | ||||
-rw-r--r-- | tools/libxc/xenctrl.h | 2 | ||||
-rw-r--r-- | tools/misc/xenpm.c | 50 | ||||
-rw-r--r-- | xen/drivers/acpi/pmstat.c | 16 | ||||
-rw-r--r-- | xen/drivers/cpufreq/cpufreq_ondemand.c | 37 | ||||
-rw-r--r-- | xen/drivers/cpufreq/utility.c | 13 | ||||
-rw-r--r-- | xen/include/acpi/cpufreq/cpufreq.h | 6 | ||||
-rw-r--r-- | xen/include/public/sysctl.h | 5 |
8 files changed, 150 insertions, 4 deletions
diff --git a/tools/libxc/xc_pm.c b/tools/libxc/xc_pm.c index bb9a80c9e2..7d588346d5 100644 --- a/tools/libxc/xc_pm.c +++ b/tools/libxc/xc_pm.c @@ -425,3 +425,28 @@ int xc_set_cpuidle_max_cstate(int xc_handle, uint32_t value) return do_sysctl(xc_handle, &sysctl); } +int xc_enable_turbo(int xc_handle, int cpuid) +{ + DECLARE_SYSCTL; + + if ( xc_handle < 0 ) + return -EINVAL; + + sysctl.cmd = XEN_SYSCTL_pm_op; + sysctl.u.pm_op.cmd = XEN_SYSCTL_pm_op_enable_turbo; + sysctl.u.pm_op.cpuid = cpuid; + return do_sysctl(xc_handle, &sysctl); +} + +int xc_disable_turbo(int xc_handle, int cpuid) +{ + DECLARE_SYSCTL; + + if ( xc_handle < 0 ) + return -EINVAL; + + sysctl.cmd = XEN_SYSCTL_pm_op; + sysctl.u.pm_op.cmd = XEN_SYSCTL_pm_op_disable_turbo; + sysctl.u.pm_op.cpuid = cpuid; + return do_sysctl(xc_handle, &sysctl); +} diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index ca6b89c09e..77566e27ff 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -1312,6 +1312,8 @@ int xc_get_vcpu_migration_delay(int xc_handle, uint32_t *value); int xc_get_cpuidle_max_cstate(int xc_handle, uint32_t *value); int xc_set_cpuidle_max_cstate(int xc_handle, uint32_t value); +int xc_enable_turbo(int xc_handle, int cpuid); +int xc_disable_turbo(int xc_handle, int cpuid); /** * tmem operations */ diff --git a/tools/misc/xenpm.c b/tools/misc/xenpm.c index 015d80a5b9..b795adc971 100644 --- a/tools/misc/xenpm.c +++ b/tools/misc/xenpm.c @@ -62,6 +62,8 @@ void show_help(void) " set-max-cstate <num> set the C-State limitation (<num> >= 0)\n" " start [seconds] start collect Cx/Px statistics,\n" " output after CTRL-C or SIGINT or several seconds.\n" + " enable-turbo-mode [cpuid] enable Turbo Mode in DBS governor.\n" + " disable-turbo-mode [cpuid] disable Turbo Mode in DBS governor.\n" ); } /* wrapper function */ @@ -527,6 +529,8 @@ static void print_cpufreq_para(int cpuid, struct xc_get_cpufreq_para *p_cpufreq) p_cpufreq->u.ondemand.sampling_rate); printf(" up_threshold : %u\n", p_cpufreq->u.ondemand.up_threshold); + printf(" turbo mode : %s\n", + p_cpufreq->u.ondemand.turbo_enabled ? "enabled" : "disabled"); } printf("scaling_avail_freq :"); @@ -951,6 +955,50 @@ void set_max_cstate_func(int argc, char *argv[]) return; } +void enable_turbo_mode(int argc, char *argv[]) +{ + int cpuid = -1; + + if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 ) + cpuid = -1; + + if ( cpuid >= max_cpu_nr ) + cpuid = -1; + + if ( cpuid < 0 ) + { + /* enable turbo modes on all cpus, + * only make effects on dbs governor */ + int i; + for ( i = 0; i < max_cpu_nr; i++ ) + xc_enable_turbo(xc_fd, i); + } + else + xc_enable_turbo(xc_fd, cpuid); +} + +void disable_turbo_mode(int argc, char *argv[]) +{ + int cpuid = -1; + + if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 ) + cpuid = -1; + + if ( cpuid >= max_cpu_nr ) + cpuid = -1; + + if ( cpuid < 0 ) + { + /* disable turbo modes on all cpus, + * only make effects on dbs governor */ + int i; + for ( i = 0; i < max_cpu_nr; i++ ) + xc_disable_turbo(xc_fd, i); + } + else + xc_disable_turbo(xc_fd, cpuid); +} + struct { const char *name; void (*function)(int argc, char *argv[]); @@ -971,6 +1019,8 @@ struct { { "get-vcpu-migration-delay", get_vcpu_migration_delay_func}, { "set-vcpu-migration-delay", set_vcpu_migration_delay_func}, { "set-max-cstate", set_max_cstate_func}, + { "enable-turbo-mode", enable_turbo_mode }, + { "disable-turbo-mode", disable_turbo_mode }, }; int main(int argc, char *argv[]) diff --git a/xen/drivers/acpi/pmstat.c b/xen/drivers/acpi/pmstat.c index fedd77b906..f152000489 100644 --- a/xen/drivers/acpi/pmstat.c +++ b/xen/drivers/acpi/pmstat.c @@ -298,7 +298,9 @@ static int get_cpufreq_para(struct xen_sysctl_pm_op *op) &op->u.get_para.u.ondemand.sampling_rate_max, &op->u.get_para.u.ondemand.sampling_rate_min, &op->u.get_para.u.ondemand.sampling_rate, - &op->u.get_para.u.ondemand.up_threshold); + &op->u.get_para.u.ondemand.up_threshold); + op->u.get_para.u.ondemand.turbo_enabled = + cpufreq_dbs_get_turbo_status(op->cpuid); } return ret; @@ -549,6 +551,18 @@ int do_pm_op(struct xen_sysctl_pm_op *op) break; } + case XEN_SYSCTL_pm_op_enable_turbo: + { + cpufreq_dbs_enable_turbo(op->cpuid); + break; + } + + case XEN_SYSCTL_pm_op_disable_turbo: + { + cpufreq_dbs_disable_turbo(op->cpuid); + break; + } + default: printk("not defined sub-hypercall @ do_pm_op\n"); ret = -ENOSYS; diff --git a/xen/drivers/cpufreq/cpufreq_ondemand.c b/xen/drivers/cpufreq/cpufreq_ondemand.c index 2e5a1c5832..799a377f53 100644 --- a/xen/drivers/cpufreq/cpufreq_ondemand.c +++ b/xen/drivers/cpufreq/cpufreq_ondemand.c @@ -58,6 +58,9 @@ static struct dbs_tuners { static struct timer dbs_timer[NR_CPUS]; +/* Turbo Mode */ +static int turbo_detected = 0; + int write_ondemand_sampling_rate(unsigned int sampling_rate) { if ( (sampling_rate > MAX_SAMPLING_RATE / MICROSECS(1)) || @@ -100,15 +103,21 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) uint64_t cur_ns, total_ns; uint64_t max_load_freq = 0; struct cpufreq_policy *policy; + unsigned int max; unsigned int j; if (!this_dbs_info->enable) return; policy = this_dbs_info->cur_policy; + max = policy->max; + if (turbo_detected && !this_dbs_info->turbo_enabled) { + if (max > policy->cpuinfo.second_max_freq) + max = policy->cpuinfo.second_max_freq; + } if (unlikely(policy->resume)) { - __cpufreq_driver_target(policy, policy->max,CPUFREQ_RELATION_H); + __cpufreq_driver_target(policy, max,CPUFREQ_RELATION_H); return; } @@ -145,9 +154,9 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) /* Check for frequency increase */ if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) { /* if we are already at full speed then break out early */ - if (policy->cur == policy->max) + if (policy->cur == max) return; - __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); + __cpufreq_driver_target(policy, max, CPUFREQ_RELATION_H); return; } @@ -265,6 +274,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event) } else dbs_tuners_ins.sampling_rate = usr_sampling_rate; } + this_dbs_info->turbo_enabled = 1; dbs_timer_init(this_dbs_info); break; @@ -335,6 +345,11 @@ struct cpufreq_governor cpufreq_gov_dbs = { static int __init cpufreq_gov_dbs_init(void) { + unsigned int eax = cpuid_eax(6); + if ( eax & 0x2 ) { + turbo_detected = 1; + printk(XENLOG_INFO "Turbo Mode detected!\n"); + } return cpufreq_register_governor(&cpufreq_gov_dbs); } __initcall(cpufreq_gov_dbs_init); @@ -379,3 +394,19 @@ void cpufreq_dbs_timer_resume(void) } } } + +void cpufreq_dbs_enable_turbo(int cpuid) +{ + per_cpu(cpu_dbs_info, cpuid).turbo_enabled = 1; +} + +void cpufreq_dbs_disable_turbo(int cpuid) +{ + per_cpu(cpu_dbs_info, cpuid).turbo_enabled = 0; +} + +unsigned int cpufreq_dbs_get_turbo_status(int cpuid) +{ + return turbo_detected && per_cpu(cpu_dbs_info, cpuid).turbo_enabled; +} + diff --git a/xen/drivers/cpufreq/utility.c b/xen/drivers/cpufreq/utility.c index 5daffedf59..c3259d1926 100644 --- a/xen/drivers/cpufreq/utility.c +++ b/xen/drivers/cpufreq/utility.c @@ -208,6 +208,7 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, { unsigned int min_freq = ~0; unsigned int max_freq = 0; + unsigned int second_max_freq = 0; unsigned int i; for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { @@ -219,9 +220,21 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, if (freq > max_freq) max_freq = freq; } + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { + unsigned int freq = table[i].frequency; + if (freq == CPUFREQ_ENTRY_INVALID || freq == max_freq) + continue; + if (freq > second_max_freq) + second_max_freq = freq; + } + if (second_max_freq == 0) + second_max_freq = max_freq; + printk(XENLOG_INFO "max_freq: %u second_max_freq: %u\n", + max_freq, second_max_freq); policy->min = policy->cpuinfo.min_freq = min_freq; policy->max = policy->cpuinfo.max_freq = max_freq; + policy->cpuinfo.second_max_freq = second_max_freq; if (policy->min == ~0) return -EINVAL; diff --git a/xen/include/acpi/cpufreq/cpufreq.h b/xen/include/acpi/cpufreq/cpufreq.h index 0cfda5d653..1f0506dd93 100644 --- a/xen/include/acpi/cpufreq/cpufreq.h +++ b/xen/include/acpi/cpufreq/cpufreq.h @@ -33,6 +33,7 @@ struct acpi_cpufreq_data { struct cpufreq_cpuinfo { unsigned int max_freq; + unsigned int second_max_freq; /* P1 if Turbo Mode is on */ unsigned int min_freq; unsigned int transition_latency; /* in 10^(-9) s = nanoseconds */ }; @@ -222,6 +223,7 @@ struct cpu_dbs_info_s { int cpu; unsigned int enable:1; unsigned int stoppable:1; + unsigned int turbo_enabled:1; }; int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event); @@ -236,4 +238,8 @@ int write_userspace_scaling_setspeed(unsigned int cpu, unsigned int freq); void cpufreq_dbs_timer_suspend(void); void cpufreq_dbs_timer_resume(void); + +void cpufreq_dbs_enable_turbo(int cpuid); +void cpufreq_dbs_disable_turbo(int cpuid); +unsigned int cpufreq_dbs_get_turbo_status(int cpuid); #endif /* __XEN_CPUFREQ_PM_H__ */ diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index bc02643ad7..b6511489b9 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -298,6 +298,7 @@ struct xen_ondemand { uint32_t sampling_rate; uint32_t up_threshold; + uint32_t turbo_enabled; }; typedef struct xen_ondemand xen_ondemand_t; @@ -390,6 +391,10 @@ struct xen_sysctl_pm_op { #define XEN_SYSCTL_pm_op_set_vcpu_migration_delay 0x24 #define XEN_SYSCTL_pm_op_get_vcpu_migration_delay 0x25 + /* enable/disable turbo mode when in dbs governor */ + #define XEN_SYSCTL_pm_op_enable_turbo 0x26 + #define XEN_SYSCTL_pm_op_disable_turbo 0x27 + uint32_t cmd; uint32_t cpuid; union { |