Re: [PATCH] x86: Calculate MHz using APERF/MPERF for cpuinfo and scaling_cur_freqy

From: Thomas Gleixner
Date: Fri Apr 01 2016 - 03:58:17 EST


On Fri, 1 Apr 2016, Len Brown wrote:
> +/*
> + * aperfmperf_snapshot_khz()
> + * On the current CPU, snapshot APERF, MPERF, and jiffies
> + * unless we already did it within 100ms
> + * calculate kHz, save snapshot
> + */
> +static void aperfmperf_snapshot_khz(void *dummy)
> +{
> + unsigned long long aperf, aperf_delta;
> + unsigned long long mperf, mperf_delta;
> + unsigned long long numerator;
> + struct aperfmperf_sample *s = &get_cpu_var(samples);

this_cpu_ptr is sufficient. That's a smp function call ...

> +
> + /* Cache KHz for 100 ms */
> + if (time_before(jiffies, s->jiffies + HZ/10))
> + goto out;
> +
> + rdmsrl(MSR_IA32_APERF, aperf);
> + rdmsrl(MSR_IA32_MPERF, mperf);
> +
> + aperf_delta = aperf - s->aperf;
> + mperf_delta = mperf - s->mperf;
> +
> + /*
> + * There is no architectural guarantee that MPERF
> + * increments faster than we can read it.
> + */
> + if (mperf_delta == 0)
> + goto out;
> +
> + numerator = cpu_khz * aperf_delta;
> + s->khz = div64_u64(numerator, mperf_delta);
> + s->jiffies = jiffies;
> + s->aperf = aperf;
> + s->mperf = mperf;
> +
> +out:
> + put_cpu_var(samples);
> +}
> +
> +unsigned int aperfmperf_khz_on_cpu(int cpu)
> +{
> + if (!cpu_khz)
> + return 0;
> +
> + if (!boot_cpu_has(X86_FEATURE_APERFMPERF))
> + return 0;
> +
> + smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, 1);

You can avoid the function call if you check s->jiffies here.

Thanks,

tglx