All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] Update cpufreq aperf and mperf read, so that it can be used by both ondemand gov and user program
@ 2009-03-20  2:47 Liu, Jinsong
  0 siblings, 0 replies; only message in thread
From: Liu, Jinsong @ 2009-03-20  2:47 UTC (permalink / raw)
  To: xen-devel; +Cc: Keir Fraser

[-- Attachment #1: Type: text/plain, Size: 456 bytes --]

Update cpufreq aperf and mperf read, so that it can be used 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>

[-- Attachment #2: px-xen-1-amperf.patch --]
[-- Type: application/octet-stream, Size: 7968 bytes --]

Update cpufreq aperf and mperf read, so that it can be used 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>

diff -r 11aa4a500f65 xen/arch/x86/acpi/cpufreq/cpufreq.c
--- a/xen/arch/x86/acpi/cpufreq/cpufreq.c	Tue Mar 17 12:18:02 2009 +0800
+++ b/xen/arch/x86/acpi/cpufreq/cpufreq.c	Thu Mar 19 21:23:51 2009 +0800
@@ -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)
+static unsigned int get_measured_perf(unsigned int cpu, unsigned int flag)
 {
-    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)
-{
-    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(un
     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);
     }
 
-    return drv_data[cpu]->max_freq * perf_percent / 100;
+    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;
+    }
+
+    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)
diff -r 11aa4a500f65 xen/drivers/cpufreq/cpufreq_ondemand.c
--- a/xen/drivers/cpufreq/cpufreq_ondemand.c	Tue Mar 17 12:18:02 2009 +0800
+++ b/xen/drivers/cpufreq/cpufreq_ondemand.c	Thu Mar 19 21:23:51 2009 +0800
@@ -161,9 +161,7 @@ static void dbs_check_cpu(struct cpu_dbs
     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);
 
diff -r 11aa4a500f65 xen/drivers/cpufreq/utility.c
--- a/xen/drivers/cpufreq/utility.c	Tue Mar 17 12:18:02 2009 +0800
+++ b/xen/drivers/cpufreq/utility.c	Thu Mar 19 21:23:51 2009 +0800
@@ -357,17 +357,23 @@ int __cpufreq_driver_target(struct cpufr
     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;
 }
 
 
diff -r 11aa4a500f65 xen/include/acpi/cpufreq/cpufreq.h
--- a/xen/include/acpi/cpufreq/cpufreq.h	Tue Mar 17 12:18:02 2009 +0800
+++ b/xen/include/acpi/cpufreq/cpufreq.h	Thu Mar 19 21:23:51 2009 +0800
@@ -106,7 +106,10 @@ extern int __cpufreq_driver_target(struc
 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);
 };
 

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2009-03-20  2:47 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-20  2:47 [PATCH 1/3] Update cpufreq aperf and mperf read, so that it can be used by both ondemand gov and user program Liu, Jinsong

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.