aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-02-08 08:48:40 +0000
committerKeir Fraser <keir.fraser@citrix.com>2010-02-08 08:48:40 +0000
commitd2a92c94a1b314750a94b902e9584200b2b507b0 (patch)
tree9b52b5ef5f93725be81e517586f08d57a8a81f31
parent43d6e1096b0df2b2ba0780fa41b525e11518e520 (diff)
downloadxen-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.c25
-rw-r--r--tools/libxc/xenctrl.h2
-rw-r--r--tools/misc/xenpm.c50
-rw-r--r--xen/drivers/acpi/pmstat.c16
-rw-r--r--xen/drivers/cpufreq/cpufreq_ondemand.c37
-rw-r--r--xen/drivers/cpufreq/utility.c13
-rw-r--r--xen/include/acpi/cpufreq/cpufreq.h6
-rw-r--r--xen/include/public/sysctl.h5
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 {