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)); |