mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-03 15:55:38 +00:00

APERF/MPERF support for cpu_power. APERF/MPERF is arch defined to be a relative scale of work capacity per logical cpu, this is assumed to include SMT and Turbo mode. APERF/MPERF are specified to both reset to 0 when either counter wraps, which is highly inconvenient, since that'll give a blimp when that happens. The manual specifies writing 0 to the counters after each read, but that's 1) too expensive, and 2) destroys the possibility of sharing these counters with other users, so we live with the blimp - the other existing user does too. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
55 lines
1.1 KiB
C
55 lines
1.1 KiB
C
#include <linux/sched.h>
|
|
#include <linux/math64.h>
|
|
#include <linux/percpu.h>
|
|
#include <linux/irqflags.h>
|
|
|
|
#include <asm/cpufeature.h>
|
|
#include <asm/processor.h>
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
static DEFINE_PER_CPU(struct aperfmperf, old_perf);
|
|
|
|
static unsigned long scale_aperfmperf(void)
|
|
{
|
|
struct aperfmperf val, *old = &__get_cpu_var(old_perf);
|
|
unsigned long ratio, flags;
|
|
|
|
local_irq_save(flags);
|
|
get_aperfmperf(&val);
|
|
local_irq_restore(flags);
|
|
|
|
ratio = calc_aperfmperf_ratio(old, &val);
|
|
*old = val;
|
|
|
|
return ratio;
|
|
}
|
|
|
|
unsigned long arch_scale_freq_power(struct sched_domain *sd, int cpu)
|
|
{
|
|
/*
|
|
* do aperf/mperf on the cpu level because it includes things
|
|
* like turbo mode, which are relevant to full cores.
|
|
*/
|
|
if (boot_cpu_has(X86_FEATURE_APERFMPERF))
|
|
return scale_aperfmperf();
|
|
|
|
/*
|
|
* maybe have something cpufreq here
|
|
*/
|
|
|
|
return default_scale_freq_power(sd, cpu);
|
|
}
|
|
|
|
unsigned long arch_scale_smt_power(struct sched_domain *sd, int cpu)
|
|
{
|
|
/*
|
|
* aperf/mperf already includes the smt gain
|
|
*/
|
|
if (boot_cpu_has(X86_FEATURE_APERFMPERF))
|
|
return SCHED_LOAD_SCALE;
|
|
|
|
return default_scale_smt_power(sd, cpu);
|
|
}
|
|
|
|
#endif
|