diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2017-11-03 11:35:49 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-03 11:50:13 -0400 |
| commit | 941f5f0f6ef5338814145cf2b813cf1f98873e2f (patch) | |
| tree | b5bfebf297b5213cb5ef96af994c5cc84b64e9bb | |
| parent | 5cb0512c02ecd7e6214e912e4c150f4219ac78e0 (diff) | |
x86: CPU: Fix up "cpu MHz" in /proc/cpuinfo
Commit 890da9cf0983 (Revert "x86: do not use cpufreq_quick_get() for
/proc/cpuinfo "cpu MHz"") is not sufficient to restore the previous
behavior of "cpu MHz" in /proc/cpuinfo on x86 due to some changes
made after the commit it has reverted.
To address this, make the code in question use arch_freq_get_on_cpu()
which also is used by cpufreq for reporting the current frequency of
CPUs and since that function doesn't really depend on cpufreq in any
way, drop the CONFIG_CPU_FREQ dependency for the object file
containing it.
Also refactor arch_freq_get_on_cpu() somewhat to avoid IPIs and
return cached values right away if it is called very often over a
short time (to prevent user space from triggering IPI storms through
it).
Fixes: 890da9cf0983 (Revert "x86: do not use cpufreq_quick_get() for /proc/cpuinfo "cpu MHz"")
Cc: stable@kernel.org # 4.13 - together with 890da9cf0983
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | arch/x86/kernel/cpu/Makefile | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/aperfmperf.c | 11 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/proc.c | 4 |
3 files changed, 11 insertions, 6 deletions
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index c60922a66385..236999c54edc 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile | |||
| @@ -22,7 +22,7 @@ obj-y += common.o | |||
| 22 | obj-y += rdrand.o | 22 | obj-y += rdrand.o |
| 23 | obj-y += match.o | 23 | obj-y += match.o |
| 24 | obj-y += bugs.o | 24 | obj-y += bugs.o |
| 25 | obj-$(CONFIG_CPU_FREQ) += aperfmperf.o | 25 | obj-y += aperfmperf.o |
| 26 | 26 | ||
| 27 | obj-$(CONFIG_PROC_FS) += proc.o | 27 | obj-$(CONFIG_PROC_FS) += proc.o |
| 28 | obj-$(CONFIG_X86_FEATURE_NAMES) += capflags.o powerflags.o | 28 | obj-$(CONFIG_X86_FEATURE_NAMES) += capflags.o powerflags.o |
diff --git a/arch/x86/kernel/cpu/aperfmperf.c b/arch/x86/kernel/cpu/aperfmperf.c index 0ee83321a313..957813e0180d 100644 --- a/arch/x86/kernel/cpu/aperfmperf.c +++ b/arch/x86/kernel/cpu/aperfmperf.c | |||
| @@ -42,10 +42,6 @@ static void aperfmperf_snapshot_khz(void *dummy) | |||
| 42 | s64 time_delta = ktime_ms_delta(now, s->time); | 42 | s64 time_delta = ktime_ms_delta(now, s->time); |
| 43 | unsigned long flags; | 43 | unsigned long flags; |
| 44 | 44 | ||
| 45 | /* Don't bother re-computing within the cache threshold time. */ | ||
| 46 | if (time_delta < APERFMPERF_CACHE_THRESHOLD_MS) | ||
| 47 | return; | ||
| 48 | |||
| 49 | local_irq_save(flags); | 45 | local_irq_save(flags); |
| 50 | rdmsrl(MSR_IA32_APERF, aperf); | 46 | rdmsrl(MSR_IA32_APERF, aperf); |
| 51 | rdmsrl(MSR_IA32_MPERF, mperf); | 47 | rdmsrl(MSR_IA32_MPERF, mperf); |
| @@ -74,6 +70,7 @@ static void aperfmperf_snapshot_khz(void *dummy) | |||
| 74 | 70 | ||
| 75 | unsigned int arch_freq_get_on_cpu(int cpu) | 71 | unsigned int arch_freq_get_on_cpu(int cpu) |
| 76 | { | 72 | { |
| 73 | s64 time_delta; | ||
| 77 | unsigned int khz; | 74 | unsigned int khz; |
| 78 | 75 | ||
| 79 | if (!cpu_khz) | 76 | if (!cpu_khz) |
| @@ -82,6 +79,12 @@ unsigned int arch_freq_get_on_cpu(int cpu) | |||
| 82 | if (!static_cpu_has(X86_FEATURE_APERFMPERF)) | 79 | if (!static_cpu_has(X86_FEATURE_APERFMPERF)) |
| 83 | return 0; | 80 | return 0; |
| 84 | 81 | ||
| 82 | /* Don't bother re-computing within the cache threshold time. */ | ||
| 83 | time_delta = ktime_ms_delta(ktime_get(), per_cpu(samples.time, cpu)); | ||
| 84 | khz = per_cpu(samples.khz, cpu); | ||
| 85 | if (khz && time_delta < APERFMPERF_CACHE_THRESHOLD_MS) | ||
| 86 | return khz; | ||
| 87 | |||
| 85 | smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, 1); | 88 | smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, 1); |
| 86 | khz = per_cpu(samples.khz, cpu); | 89 | khz = per_cpu(samples.khz, cpu); |
| 87 | if (khz) | 90 | if (khz) |
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 6b7e17bf0b71..4378a729b933 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c | |||
| @@ -78,9 +78,11 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
| 78 | seq_printf(m, "microcode\t: 0x%x\n", c->microcode); | 78 | seq_printf(m, "microcode\t: 0x%x\n", c->microcode); |
| 79 | 79 | ||
| 80 | if (cpu_has(c, X86_FEATURE_TSC)) { | 80 | if (cpu_has(c, X86_FEATURE_TSC)) { |
| 81 | unsigned int freq = cpufreq_quick_get(cpu); | 81 | unsigned int freq = arch_freq_get_on_cpu(cpu); |
| 82 | 82 | ||
| 83 | if (!freq) | 83 | if (!freq) |
| 84 | freq = cpufreq_quick_get(cpu); | ||
| 85 | if (!freq) | ||
| 84 | freq = cpu_khz; | 86 | freq = cpu_khz; |
| 85 | seq_printf(m, "cpu MHz\t\t: %u.%03u\n", | 87 | seq_printf(m, "cpu MHz\t\t: %u.%03u\n", |
| 86 | freq / 1000, (freq % 1000)); | 88 | freq / 1000, (freq % 1000)); |
