1#include <linux/kernel.h> 2#include <linux/smp.h> 3#include <linux/module.h> 4#include <linux/init.h> 5#include <linux/cpufreq.h> 6#include <linux/slab.h> 7 8#include "mperf.h" 9 10static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf); 11 12/* Called via smp_call_function_single(), on the target CPU */ 13static void read_measured_perf_ctrs(void *_cur) 14{ 15 struct aperfmperf *am = _cur; 16 17 get_aperfmperf(am); 18} 19 20/* 21 * Return the measured active (C0) frequency on this CPU since last call 22 * to this function. 23 * Input: cpu number 24 * Return: Average CPU frequency in terms of max frequency (zero on error) 25 * 26 * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance 27 * over a period of time, while CPU is in C0 state. 28 * IA32_MPERF counts at the rate of max advertised frequency 29 * IA32_APERF counts at the rate of actual CPU frequency 30 * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and 31 * no meaning should be associated with absolute values of these MSRs. 32 */ 33unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy, 34 unsigned int cpu) 35{ 36 struct aperfmperf perf; 37 unsigned long ratio; 38 unsigned int retval; 39 40 if (smp_call_function_single(cpu, read_measured_perf_ctrs, &perf, 1)) 41 return 0; 42 43 ratio = calc_aperfmperf_ratio(&per_cpu(acfreq_old_perf, cpu), &perf); 44 per_cpu(acfreq_old_perf, cpu) = perf; 45 46 retval = (policy->cpuinfo.max_freq * ratio) >> APERFMPERF_SHIFT; 47 48 return retval; 49} 50EXPORT_SYMBOL_GPL(cpufreq_get_measured_perf); 51MODULE_LICENSE("GPL"); 52