summaryrefslogtreecommitdiff
path: root/xen/arch/x86/acpi/cpufreq
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-05-07 09:46:50 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-05-07 09:46:50 +0100
commit40af606c02e8caaa824213a7eb2232c6b166dc88 (patch)
treeba4af4f8b075b6362101bb7185f2b8b5c5f269fa /xen/arch/x86/acpi/cpufreq
parentc4826676c4550e36296f34dc48228cf91af5a86d (diff)
x86/cpufreq: fix turbo mode detection
{acpi,powernow}_cpufreq_cpu_init() generally don't run on the CPU the policy they deal with is related to, hence using cpuid() directly works only as long as all CPUs in the system are identical (which admittedly is commonly the case). Further add a per-policy flag indicating the availability of APERF/MPERF MSRs, so that globally setting the .getavg accessor won't be a problem on heterogeneous configurations. Signed-off-by: Jan Beulich <jbeulich@novell.com>
Diffstat (limited to 'xen/arch/x86/acpi/cpufreq')
-rw-r--r--xen/arch/x86/acpi/cpufreq/cpufreq.c36
-rw-r--r--xen/arch/x86/acpi/cpufreq/powernow.c35
2 files changed, 46 insertions, 25 deletions
diff --git a/xen/arch/x86/acpi/cpufreq/cpufreq.c b/xen/arch/x86/acpi/cpufreq/cpufreq.c
index af591ee94f..6948d7d816 100644
--- a/xen/arch/x86/acpi/cpufreq/cpufreq.c
+++ b/xen/arch/x86/acpi/cpufreq/cpufreq.c
@@ -280,7 +280,7 @@ unsigned int get_measured_perf(unsigned int cpu, unsigned int flag)
return 0;
policy = cpufreq_cpu_policy[cpu];
- if (!policy)
+ if (!policy || !policy->aperf_mperf)
return 0;
switch (flag)
@@ -377,6 +377,26 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
return freq;
}
+static void feature_detect(void *info)
+{
+ struct cpufreq_policy *policy = info;
+ unsigned int eax, ecx;
+
+ ecx = cpuid_ecx(6);
+ if (ecx & CPUID_6_ECX_APERFMPERF_CAPABILITY) {
+ policy->aperf_mperf = 1;
+ acpi_cpufreq_driver.getavg = get_measured_perf;
+ }
+
+ eax = cpuid_eax(6);
+ if (eax & 0x2) {
+ policy->turbo = CPUFREQ_TURBO_ENABLED;
+ if (cpufreq_verbose)
+ printk(XENLOG_INFO "CPU%u: Turbo Mode detected and enabled\n",
+ smp_processor_id());
+ }
+}
+
static unsigned int check_freqs(cpumask_t mask, unsigned int freq,
struct acpi_cpufreq_data *data)
{
@@ -615,18 +635,8 @@ acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
/* Check for APERF/MPERF support in hardware
* also check for boost support */
- if (c->x86_vendor == X86_VENDOR_INTEL && c->cpuid_level >= 6) {
- unsigned int ecx;
- unsigned int eax;
- ecx = cpuid_ecx(6);
- if (ecx & CPUID_6_ECX_APERFMPERF_CAPABILITY)
- acpi_cpufreq_driver.getavg = get_measured_perf;
- eax = cpuid_eax(6);
- if ( eax & 0x2 ) {
- policy->turbo = CPUFREQ_TURBO_ENABLED;
- printk(XENLOG_INFO "Turbo Mode detected and enabled!\n");
- }
- }
+ if (c->x86_vendor == X86_VENDOR_INTEL && c->cpuid_level >= 6)
+ on_selected_cpus(cpumask_of(cpu), feature_detect, policy, 1);
/*
* the first call to ->target() should result in us actually
diff --git a/xen/arch/x86/acpi/cpufreq/powernow.c b/xen/arch/x86/acpi/cpufreq/powernow.c
index 3d34c0512b..27b53372d2 100644
--- a/xen/arch/x86/acpi/cpufreq/powernow.c
+++ b/xen/arch/x86/acpi/cpufreq/powernow.c
@@ -165,6 +165,27 @@ static int powernow_cpufreq_verify(struct cpufreq_policy *policy)
return cpufreq_frequency_table_verify(policy, data->freq_table);
}
+static void feature_detect(void *info)
+{
+ struct cpufreq_policy *policy = info;
+ unsigned int ecx, edx;
+
+ ecx = cpuid_ecx(6);
+ if (ecx & CPUID_6_ECX_APERFMPERF_CAPABILITY) {
+ policy->aperf_mperf = 1;
+ powernow_cpufreq_driver.getavg = get_measured_perf;
+ }
+
+ edx = cpuid_edx(CPUID_FREQ_VOLT_CAPABILITIES);
+ if ((edx & CPB_CAPABLE) == CPB_CAPABLE) {
+ policy->turbo = CPUFREQ_TURBO_ENABLED;
+ if (cpufreq_verbose)
+ printk(XENLOG_INFO
+ "CPU%u: Core Boost/Turbo detected and enabled\n",
+ smp_processor_id());
+ }
+}
+
static int powernow_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
unsigned int i;
@@ -250,18 +271,8 @@ static int powernow_cpufreq_cpu_init(struct cpufreq_policy *policy)
if (result)
goto err_freqfree;
- if (c->cpuid_level >= 6) {
- unsigned int edx;
- unsigned int ecx;
- ecx = cpuid_ecx(6);
- if (ecx & CPUID_6_ECX_APERFMPERF_CAPABILITY)
- powernow_cpufreq_driver.getavg = get_measured_perf;
- edx = cpuid_edx(CPUID_FREQ_VOLT_CAPABILITIES);
- if ((edx & CPB_CAPABLE) == CPB_CAPABLE) {
- policy->turbo = CPUFREQ_TURBO_ENABLED;
- printk(XENLOG_INFO "Core Boost/Turbo detected and enabled\n");
- }
- }
+ if (c->cpuid_level >= 6)
+ on_selected_cpus(cpumask_of(cpu), feature_detect, policy, 1);
/*
* the first call to ->target() should result in us actually