]> xenbits.xensource.com Git - xen.git/commitdiff
cpufreq: Update cpufreq aperf and mperf read, so that it can be used
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 20 Mar 2009 08:48:17 +0000 (08:48 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 20 Mar 2009 08:48:17 +0000 (08:48 +0000)
by both ondemand gov and user program

Current __get_measured_perf read aperf and mperf MSR and then clear
them for the sake of ondemand governor. This solution block user
program to get aperf and mperf on their purpose. In this patch, it no
longer clear aperf and mperf MSR, so that it can be used by both
ondemand gov and user program.

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
xen/arch/x86/acpi/cpufreq/cpufreq.c
xen/drivers/cpufreq/cpufreq_ondemand.c
xen/drivers/cpufreq/utility.c
xen/include/acpi/cpufreq/cpufreq.h

index ae01fadbc982156134b6c67266315d70789fdf3c..cda7fb40aa28511e9fc92da5f455f9c4dba82ebd 100644 (file)
@@ -232,6 +232,26 @@ static u32 get_cur_val(cpumask_t mask)
     return cmd.val;
 }
 
+struct perf_pair {
+    union {
+        struct {
+            uint32_t lo;
+            uint32_t hi;
+        } split;
+        uint64_t whole;
+    } aperf, mperf;
+};
+static DEFINE_PER_CPU(struct perf_pair, gov_perf_pair);
+static DEFINE_PER_CPU(struct perf_pair, usr_perf_pair);
+
+static void read_measured_perf_ctrs(void *_readin)
+{
+    struct perf_pair *readin = _readin;
+
+    rdmsr(MSR_IA32_APERF, readin->aperf.split.lo, readin->aperf.split.hi);
+    rdmsr(MSR_IA32_MPERF, readin->mperf.split.lo, readin->mperf.split.hi);
+}
+
 /*
  * Return the measured active (C0) frequency on this CPU since last call
  * to this function.
@@ -245,40 +265,13 @@ 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.
  */
-static void  __get_measured_perf(void *perf_percent)
-{
-    unsigned int *ratio = perf_percent;
-    union {
-        struct {
-            uint32_t lo;
-            uint32_t hi;
-        } split;
-        uint64_t whole;
-    } aperf_cur, mperf_cur;
-
-    rdmsr(MSR_IA32_APERF, aperf_cur.split.lo, aperf_cur.split.hi);
-    rdmsr(MSR_IA32_MPERF, mperf_cur.split.lo, mperf_cur.split.hi);
-
-    wrmsr(MSR_IA32_APERF, 0,0);
-    wrmsr(MSR_IA32_MPERF, 0,0);
-
-    if (unlikely(((unsigned long)(-1) / 100) < aperf_cur.whole)) {
-        int shift_count = 7;
-        aperf_cur.whole >>= shift_count;
-        mperf_cur.whole >>= shift_count;
-    }
-
-    if (aperf_cur.whole && mperf_cur.whole)
-        *ratio = (aperf_cur.whole * 100) / mperf_cur.whole;
-    else
-        *ratio = 0;
-}
-
-static unsigned int get_measured_perf(unsigned int cpu)
+static unsigned int get_measured_perf(unsigned int cpu, unsigned int flag)
 {
-    struct cpufreq_policy *policy;
+    struct cpufreq_policy *policy;    
+    struct perf_pair readin, cur, *saved;
     unsigned int perf_percent;
     cpumask_t cpumask;
+    unsigned int retval;
 
     if (!cpu_online(cpu))
         return 0;
@@ -287,16 +280,80 @@ static unsigned int get_measured_perf(unsigned int cpu)
     if (!policy)
         return 0;
 
-    /* Usually we take the short path (no IPI) for the sake of performance. */
+    switch (flag)
+    {
+    case GOV_GETAVG:
+    {
+        saved = &per_cpu(gov_perf_pair, cpu);
+        break;
+    }
+    case USR_GETAVG:
+    {
+        saved = &per_cpu(usr_perf_pair, cpu);
+        break;
+    }
+    default:
+        return 0;
+    }
+
     if (cpu == smp_processor_id()) {
-        __get_measured_perf((void *)&perf_percent);
+        read_measured_perf_ctrs((void *)&readin);
     } else {
         cpumask = cpumask_of_cpu(cpu);
-        on_selected_cpus(cpumask, __get_measured_perf, 
-                        (void *)&perf_percent,0,1);
+        on_selected_cpus(cpumask, read_measured_perf_ctrs, 
+                        (void *)&readin, 0, 1);
+    }
+
+    cur.aperf.whole = readin.aperf.whole - saved->aperf.whole;
+    cur.mperf.whole = readin.mperf.whole - saved->mperf.whole;
+    saved->aperf.whole = readin.aperf.whole;
+    saved->mperf.whole = readin.mperf.whole;
+
+#ifdef __i386__
+    /*
+     * We dont want to do 64 bit divide with 32 bit kernel
+     * Get an approximate value. Return failure in case we cannot get
+     * an approximate value.
+     */
+    if (unlikely(cur.aperf.split.hi || cur.mperf.split.hi)) {
+        int shift_count;
+        uint32_t h;
+
+        h = max_t(uint32_t, cur.aperf.split.hi, cur.mperf.split.hi);
+        shift_count = fls(h);
+
+        cur.aperf.whole >>= shift_count;
+        cur.mperf.whole >>= shift_count;
+    }
+
+    if (((unsigned long)(-1) / 100) < cur.aperf.split.lo) {
+        int shift_count = 7;
+        cur.aperf.split.lo >>= shift_count;
+        cur.mperf.split.lo >>= shift_count;
+    }
+
+    if (cur.aperf.split.lo && cur.mperf.split.lo)
+        perf_percent = (cur.aperf.split.lo * 100) / cur.mperf.split.lo;
+    else
+        perf_percent = 0;
+
+#else
+    if (unlikely(((unsigned long)(-1) / 100) < cur.aperf.whole)) {
+        int shift_count = 7;
+        cur.aperf.whole >>= shift_count;
+        cur.mperf.whole >>= shift_count;
     }
 
-    return drv_data[cpu]->max_freq * perf_percent / 100;
+    if (cur.aperf.whole && cur.mperf.whole)
+        perf_percent = (cur.aperf.whole * 100) / cur.mperf.whole;
+    else
+        perf_percent = 0;
+
+#endif
+
+    retval = drv_data[policy->cpu]->max_freq * perf_percent / 100;
+
+    return retval;
 }
 
 static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
index 9a0a940649598d4932854a9b94ee36c020a7eb09..b01312d9afda585dfc570d6e800ec271d9966fe4 100644 (file)
@@ -161,9 +161,7 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
     if (load < (dbs_tuners_ins.up_threshold - 10)) {
         unsigned int freq_next, freq_cur;
 
-        freq_cur = __cpufreq_driver_getavg(policy);
-        if (!freq_cur)
-            freq_cur = policy->cur;
+        freq_cur = cpufreq_driver_getavg(policy->cpu, GOV_GETAVG);
 
         freq_next = (freq_cur * load) / (dbs_tuners_ins.up_threshold - 10);
 
index 91225b9199cf4e55c0336fcb601752dcfe4012ef..5daffedf593e958b93bffe81d47472e801f4269f 100644 (file)
@@ -357,17 +357,23 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
     return retval;
 }
 
-int __cpufreq_driver_getavg(struct cpufreq_policy *policy)
+int cpufreq_driver_getavg(unsigned int cpu, unsigned int flag)
 {
-    int ret = 0;
+    struct cpufreq_policy *policy;
+    int freq_avg;
 
-    if (!policy)
-        return -EINVAL;
+    policy = cpufreq_cpu_policy[cpu];
+    if (!cpu_online(cpu) || !policy)
+        return 0;
 
-    if (cpu_online(policy->cpu) && cpufreq_driver->getavg)
-        ret = cpufreq_driver->getavg(policy->cpu);
+    if (cpufreq_driver->getavg)
+    {
+        freq_avg = cpufreq_driver->getavg(cpu, flag);
+        if (freq_avg > 0)
+            return freq_avg;
+    }
 
-    return ret;
+    return policy->cur;
 }
 
 
index bc525862bcbe0aa44e9115b1b899dafc380b787b..8423664efe17ab5392c5c055a524940f101c801f 100644 (file)
@@ -106,7 +106,10 @@ extern struct cpufreq_governor *__find_governor(const char *governor);
 extern int __cpufreq_driver_target(struct cpufreq_policy *policy,
                                    unsigned int target_freq,
                                    unsigned int relation);
-extern int __cpufreq_driver_getavg(struct cpufreq_policy *policy);
+
+#define GOV_GETAVG     1
+#define USR_GETAVG     2
+extern int cpufreq_driver_getavg(unsigned int cpu, unsigned int flag);
 
 static __inline__ int 
 __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
@@ -130,7 +133,7 @@ struct cpufreq_driver {
                      unsigned int target_freq,
                      unsigned int relation);
     unsigned int    (*get)(unsigned int cpu);
-    unsigned int    (*getavg)(unsigned int cpu);
+    unsigned int    (*getavg)(unsigned int cpu, unsigned int flag);
     int    (*exit)(struct cpufreq_policy *policy);
 };