aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-11-03 11:35:49 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-11-03 11:50:13 -0400
commit941f5f0f6ef5338814145cf2b813cf1f98873e2f (patch)
treeb5bfebf297b5213cb5ef96af994c5cc84b64e9bb
parent5cb0512c02ecd7e6214e912e4c150f4219ac78e0 (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/Makefile2
-rw-r--r--arch/x86/kernel/cpu/aperfmperf.c11
-rw-r--r--arch/x86/kernel/cpu/proc.c4
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
22obj-y += rdrand.o 22obj-y += rdrand.o
23obj-y += match.o 23obj-y += match.o
24obj-y += bugs.o 24obj-y += bugs.o
25obj-$(CONFIG_CPU_FREQ) += aperfmperf.o 25obj-y += aperfmperf.o
26 26
27obj-$(CONFIG_PROC_FS) += proc.o 27obj-$(CONFIG_PROC_FS) += proc.o
28obj-$(CONFIG_X86_FEATURE_NAMES) += capflags.o powerflags.o 28obj-$(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
75unsigned int arch_freq_get_on_cpu(int cpu) 71unsigned 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));