^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * x86 APERF/MPERF KHz calculation for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * /sys/.../cpufreq/scaling_cur_freq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2017 Intel Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author: Len Brown <len.brown@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/ktime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/math64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/percpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/cpufreq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/sched/isolation.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "cpu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct aperfmperf_sample {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) unsigned int khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) ktime_t time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) u64 aperf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) u64 mperf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static DEFINE_PER_CPU(struct aperfmperf_sample, samples);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define APERFMPERF_CACHE_THRESHOLD_MS 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define APERFMPERF_REFRESH_DELAY_MS 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define APERFMPERF_STALE_THRESHOLD_MS 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * aperfmperf_snapshot_khz()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * On the current CPU, snapshot APERF, MPERF, and jiffies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * unless we already did it within 10ms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * calculate kHz, save snapshot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void aperfmperf_snapshot_khz(void *dummy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u64 aperf, aperf_delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) u64 mperf, mperf_delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct aperfmperf_sample *s = this_cpu_ptr(&samples);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) rdmsrl(MSR_IA32_APERF, aperf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) rdmsrl(MSR_IA32_MPERF, mperf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) aperf_delta = aperf - s->aperf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) mperf_delta = mperf - s->mperf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * There is no architectural guarantee that MPERF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * increments faster than we can read it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (mperf_delta == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) s->time = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) s->aperf = aperf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) s->mperf = mperf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) s->khz = div64_u64((cpu_khz * aperf_delta), mperf_delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static bool aperfmperf_snapshot_cpu(int cpu, ktime_t now, bool wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) s64 time_delta = ktime_ms_delta(now, per_cpu(samples.time, cpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* Don't bother re-computing within the cache threshold time. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (time_delta < APERFMPERF_CACHE_THRESHOLD_MS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* Return false if the previous iteration was too long ago. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return time_delta <= APERFMPERF_STALE_THRESHOLD_MS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned int aperfmperf_get_khz(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (!cpu_khz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (!boot_cpu_has(X86_FEATURE_APERFMPERF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (!housekeeping_cpu(cpu, HK_FLAG_MISC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) aperfmperf_snapshot_cpu(cpu, ktime_get(), true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return per_cpu(samples.khz, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) void arch_freq_prepare_all(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) ktime_t now = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) bool wait = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (!cpu_khz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (!boot_cpu_has(X86_FEATURE_APERFMPERF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) for_each_online_cpu(cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (!housekeeping_cpu(cpu, HK_FLAG_MISC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (!aperfmperf_snapshot_cpu(cpu, now, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) wait = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) msleep(APERFMPERF_REFRESH_DELAY_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) unsigned int arch_freq_get_on_cpu(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (!cpu_khz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (!boot_cpu_has(X86_FEATURE_APERFMPERF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (!housekeeping_cpu(cpu, HK_FLAG_MISC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (aperfmperf_snapshot_cpu(cpu, ktime_get(), true))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return per_cpu(samples.khz, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) msleep(APERFMPERF_REFRESH_DELAY_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return per_cpu(samples.khz, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }