linux/drivers/cpufreq/mperf.c
<<
>>
Prefs
   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