Modify cpupower to schedule itself on each of the cpus in the system and
then get the APERF/MPERF register values.

This is advantageous because an IPI is not generated when a read_msr() is
executed on the local logical CPU thereby reducing the chance of having
APERF and MPERF being out of sync.

Signed-off-by: Janakarajan Natarajan <janakarajan.natara...@amd.com>
---
 .../utils/idle_monitor/mperf_monitor.c        | 38 ++++++++++++++-----
 1 file changed, 28 insertions(+), 10 deletions(-)

diff --git a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c 
b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
index 44806a6dae11..8b072e39c897 100644
--- a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
+++ b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
@@ -10,6 +10,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <limits.h>
+#include <sched.h>
 
 #include <cpufreq.h>
 
@@ -86,15 +87,33 @@ static int mperf_get_tsc(unsigned long long *tsc)
        return ret;
 }
 
+static int get_aperf_mperf(int cpu, unsigned long long *aval,
+                          unsigned long long *mval)
+{
+       cpu_set_t set;
+       int ret;
+
+       CPU_ZERO(&set);
+       CPU_SET(cpu, &set);
+       if (sched_setaffinity(getpid(), sizeof(set), &set) == -1) {
+               dprint("Could not migrate to cpu: %d\n", cpu);
+               return 1;
+       }
+
+       ret = read_msr(cpu, MSR_APERF, aval);
+       ret |= read_msr(cpu, MSR_MPERF, mval);
+
+       return ret;
+}
+
 static int mperf_init_stats(unsigned int cpu)
 {
-       unsigned long long val;
+       unsigned long long aval, mval;
        int ret;
 
-       ret = read_msr(cpu, MSR_APERF, &val);
-       aperf_previous_count[cpu] = val;
-       ret |= read_msr(cpu, MSR_MPERF, &val);
-       mperf_previous_count[cpu] = val;
+       ret = get_aperf_mperf(cpu, &aval, &mval);
+       aperf_previous_count[cpu] = aval;
+       mperf_previous_count[cpu] = mval;
        is_valid[cpu] = !ret;
 
        return 0;
@@ -102,13 +121,12 @@ static int mperf_init_stats(unsigned int cpu)
 
 static int mperf_measure_stats(unsigned int cpu)
 {
-       unsigned long long val;
+       unsigned long long aval, mval;
        int ret;
 
-       ret = read_msr(cpu, MSR_APERF, &val);
-       aperf_current_count[cpu] = val;
-       ret |= read_msr(cpu, MSR_MPERF, &val);
-       mperf_current_count[cpu] = val;
+       ret = get_aperf_mperf(cpu, &aval, &mval);
+       aperf_current_count[cpu] = aval;
+       mperf_current_count[cpu] = mval;
        is_valid[cpu] = !ret;
 
        return 0;
-- 
2.17.1

Reply via email to