x86: Fix APERF/MPERF query bug on non-current cpu
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 18 Jul 2008 10:24:13 +0000 (11:24 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 18 Jul 2008 10:24:13 +0000 (11:24 +0100)
Currently xen hypervisor cpufreq can only query APERF/MPERF on running
cpu, which will result in system broken when query on non-current
cpu. This patch fix the APERF/MPERF query bug on non-current cpu.

Signed-off-by: Liu Jinsong <jinsong.liu@intel.com>
xen/arch/x86/acpi/cpufreq/cpufreq.c

index cabe94ea93fe3d55403a0458767d4103ca426240..58147da55beadcc3ecbe2b003faa22e59f034af3 100644 (file)
@@ -237,9 +237,9 @@ static u32 get_cur_val(cpumask_t mask)
  * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and
  * no meaning should be associated with absolute values of these MSRs.
  */
-/* FIXME: handle query on non-current cpu later */
-static unsigned int get_measured_perf(unsigned int cpu)
+static void  __get_measured_perf(void *perf_percent)
 {
+    unsigned int *ratio = perf_percent;
     union {
         struct {
             uint32_t lo;
@@ -248,9 +248,6 @@ static unsigned int get_measured_perf(unsigned int cpu)
         uint64_t whole;
     } aperf_cur, mperf_cur;
 
-    unsigned int perf_percent;
-    unsigned int retval;
-
     rdmsr(MSR_IA32_APERF, aperf_cur.split.lo, aperf_cur.split.hi);
     rdmsr(MSR_IA32_MPERF, mperf_cur.split.lo, mperf_cur.split.hi);
 
@@ -264,10 +261,21 @@ static unsigned int get_measured_perf(unsigned int cpu)
     }
 
     if (aperf_cur.whole && mperf_cur.whole)
-        perf_percent = (aperf_cur.whole * 100) / mperf_cur.whole;
+        *ratio = (aperf_cur.whole * 100) / mperf_cur.whole;
     else
-        perf_percent = 0;
+        *ratio = 0;
+}
+
+static unsigned int get_measured_perf(unsigned int cpu)
+{
+    unsigned int retval, perf_percent;
+    cpumask_t cpumask;
+
+    if (!cpu_online(cpu))
+        return 0;
 
+    cpumask = cpumask_of_cpu(cpu);
+    on_selected_cpus(cpumask, __get_measured_perf, (void *)&perf_percent,0,1);
 
     retval = drv_data[cpu]->max_freq * perf_percent / 100;
     return retval;