Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1367801 > unrolled thread
| Started by | Len Brown <lenb@kernel.org> |
|---|---|
| First post | 2016-03-31 06:20 +0200 |
| Last post | 2016-03-31 06:20 +0200 |
| Articles | 6 — 1 participant |
Back to article view | Back to linux.kernel
[PATCH 0/9] x86: TSC calibration update Len Brown <lenb@kernel.org> - 2016-03-31 06:20 +0200
[PATCH 6/9] x86 tsc_msr: Extend to include Intel Core Architecture Len Brown <lenb@kernel.org> - 2016-03-31 06:20 +0200
[PATCH 2/9] x86 tsc_msr: Remove debugging messages Len Brown <lenb@kernel.org> - 2016-03-31 06:20 +0200
[PATCH 9/9] x86 tsc: enumerate BXT tsc_khz via CPUID Len Brown <lenb@kernel.org> - 2016-03-31 06:20 +0200
[PATCH 4/9] x86 tsc_msr: Correct Silvermont reference clock values Len Brown <lenb@kernel.org> - 2016-03-31 06:20 +0200
[PATCH 5/9] x86 tsc_msr: Add Airmont reference clock values Len Brown <lenb@kernel.org> - 2016-03-31 06:20 +0200
| From | Len Brown <lenb@kernel.org> |
|---|---|
| Date | 2016-03-31 06:20 +0200 |
| Subject | [PATCH 0/9] x86: TSC calibration update |
| Message-ID | <riCfn-7Lb-3@gated-at.bofh.it> |
cpu_khz and tsc_khz initialization can be unreliable and expensive.
They are initialized in tsc_init()/native_calibrate_tsc(), which prints:
pr_info("Detected %lu.%03lu MHz processor\n", cpu_khz...)
native_calibrate_cpu() first tries quick_pit_calibrate(),
which can take over 50.0M cycles to succeed,
or as few as 2.4M cycles to fail.
On failure, pit_calibrate_tsc() is attempted, which can succeed
in as few as 20M cycles, but may consume over 240M cycles
before it fails.
By comparison, on many processors, tsc frequency can be discovered by
table and MSR or CPUID in under 0.002M cycles.
Subsequently tsc_refine_calibration_work() checks our work,
but it takes under 0.004M cycles.
pr_info("Refined TSC clocksource calibration: %lu.%03lu MHz\n", tsc_khz...)
Finally, CPU and TSC frequency are not guaranteed to be identical,
and this series allows cpu_khz and tsc_khz to differ
within a few percent.
cheers,
Len Brown, Intel Open Source Technology Center
this patch set is also available via git:
git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git x86
Bin Gao (1):
x86 tsc: enumerate BXT tsc_khz via CPUID
Len Brown (8):
x86 tsc_msr: Identify Intel-specific code
x86 tsc_msr: Remove debugging messages
x86 tsc_msr: Update comments, expand definitions
x86 tsc_msr: Correct Silvermont reference clock values
x86 tsc_msr: Add Airmont reference clock values
x86 tsc_msr: Extend to include Intel Core Architecture
x86 tsc_msr: Remove irqoff around MSR-based TSC enumeration
x86 tsc: enumerate SKL cpu_khz and tsc_khz via CPUID
arch/x86/include/asm/tsc.h | 4 +-
arch/x86/include/asm/x86_init.h | 4 +-
arch/x86/kernel/tsc.c | 96 ++++++++++++++++++++++++++++++----
arch/x86/kernel/tsc_msr.c | 112 ++++++++++++++++++++++------------------
arch/x86/kernel/x86_init.c | 1 +
5 files changed, 152 insertions(+), 65 deletions(-)
[toc] | [next] | [standalone]
| From | Len Brown <lenb@kernel.org> |
|---|---|
| Date | 2016-03-31 06:20 +0200 |
| Subject | [PATCH 6/9] x86 tsc_msr: Extend to include Intel Core Architecture |
| Message-ID | <riCfp-7Lb-11@gated-at.bofh.it> |
| In reply to | #1367801 |
From: Len Brown <len.brown@intel.com>
tsc_msr is used to quickly and reliably
enumerate the CPU/TSC frequencies at boot time
For the Intel Atom Architecture.
Extend tsc_msr to include recent Intel Core Architecture.
As this code discovers BCLK, it also sets lapic_timer_frequency,
which allows LAPIC timer calibration to be skipped,
though it is already skipped on systems with a TSC deadline timer.
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/x86/kernel/tsc_msr.c | 49 +++++++++++++++++++++++++++++++++++++++--------
1 file changed, 41 insertions(+), 8 deletions(-)
diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c
index 59c371e..c8ea977 100644
--- a/arch/x86/kernel/tsc_msr.c
+++ b/arch/x86/kernel/tsc_msr.c
@@ -77,23 +77,56 @@ unsigned long try_msr_calibrate_tsc(void)
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
return 0;
+ /*
+ * 100 MHz BCLK Core Architecture -- before SKL.
+ * De-rate 100Mhz by about 0.25% to account
+ * for the average effect of spread-spectrum clocking.
+ */
+ switch (boot_cpu_data.x86_model) {
+
+ case 0x2A: /* SNB */
+ case 0x3A: /* IVB */
+ freq = 99773;
+ goto get_ratio;
+ case 0x2D: /* SNB Xeon */
+ case 0x3E: /* IVB Xeon */
+ freq = 99760;
+ goto get_ratio;
+ case 0x3C: /* HSW */
+ case 0x3F: /* HSW */
+ case 0x45: /* HSW */
+ case 0x46: /* HSW */
+ case 0x3D: /* BDW */
+ case 0x47: /* BDW */
+ case 0x4F: /* BDX */
+ case 0x56: /* BDX-DE */
+ freq = 99769;
+ goto get_ratio;
+ }
+
+ /*
+ * Atom Architecture
+ */
cpu_index = match_cpu(boot_cpu_data.x86, boot_cpu_data.x86_model);
if (cpu_index < 0)
return 0;
- if (freq_desc_tables[cpu_index].msr_plat) {
- rdmsr(MSR_PLATFORM_INFO, lo, hi);
- ratio = (lo >> 8) & 0x1f;
- } else {
- rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
- ratio = (hi >> 8) & 0x1f;
- }
-
/* Get FSB FREQ ID */
rdmsr(MSR_FSB_FREQ, lo, hi);
freq_id = lo & 0x7;
freq = id_to_freq(cpu_index, freq_id);
+ if (!freq_desc_tables[cpu_index].msr_plat) {
+ rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+ ratio = (hi >> 8) & 0x1f;
+ goto done;
+ }
+
+get_ratio:
+ rdmsr(MSR_PLATFORM_INFO, lo, hi);
+ ratio = (lo >> 8) & 0x1f;
+
+done:
/* TSC frequency = maximum resolved freq * maximum resolved bus ratio */
res = freq * ratio;
--
2.8.0.rc4.16.g56331f8
[toc] | [prev] | [next] | [standalone]
| From | Len Brown <lenb@kernel.org> |
|---|---|
| Date | 2016-03-31 06:20 +0200 |
| Subject | [PATCH 2/9] x86 tsc_msr: Remove debugging messages |
| Message-ID | <riCfp-7Lb-15@gated-at.bofh.it> |
| In reply to | #1367801 |
From: Len Brown <len.brown@intel.com>
Debugging messages are not necessary after all of the
possible hardware failures that never occur.
Instead, this code can simply return 0.
This code also doesn't need to print in the success case.
tsc_init() already prints the TSC frequency,
and apic=debug is available if anybody really is
interested in printing the LAPIC frequency.
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/x86/kernel/tsc_msr.c | 19 +++----------------
1 file changed, 3 insertions(+), 16 deletions(-)
diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c
index c16e35b..d460ef1 100644
--- a/arch/x86/kernel/tsc_msr.c
+++ b/arch/x86/kernel/tsc_msr.c
@@ -76,9 +76,10 @@ static int match_cpu(u8 family, u8 model)
(freq_desc_tables[cpu_index].freqs[freq_id])
/*
- * Do MSR calibration only for known/supported CPUs.
+ * MSR-based CPU/TSC frequency discovery for certain CPUs.
*
- * Returns the calibration value or 0 if MSR calibration failed.
+ * Set global "lapic_timer_frequency" to bus_clock_cycles/jiffy
+ * Return processor base frequency in KHz, or 0 on failure.
*/
unsigned long try_msr_calibrate_tsc(void)
{
@@ -100,31 +101,17 @@ unsigned long try_msr_calibrate_tsc(void)
rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
ratio = (hi >> 8) & 0x1f;
}
- pr_info("Maximum core-clock to bus-clock ratio: 0x%x\n", ratio);
-
- if (!ratio)
- goto fail;
/* Get FSB FREQ ID */
rdmsr(MSR_FSB_FREQ, lo, hi);
freq_id = lo & 0x7;
freq = id_to_freq(cpu_index, freq_id);
- pr_info("Resolved frequency ID: %u, frequency: %u KHz\n",
- freq_id, freq);
- if (!freq)
- goto fail;
/* TSC frequency = maximum resolved freq * maximum resolved bus ratio */
res = freq * ratio;
- pr_info("TSC runs at %lu KHz\n", res);
#ifdef CONFIG_X86_LOCAL_APIC
lapic_timer_frequency = (freq * 1000) / HZ;
- pr_info("lapic_timer_frequency = %d\n", lapic_timer_frequency);
#endif
return res;
-
-fail:
- pr_warn("Fast TSC calibration using MSR failed\n");
- return 0;
}
--
2.8.0.rc4.16.g56331f8
[toc] | [prev] | [next] | [standalone]
| From | Len Brown <lenb@kernel.org> |
|---|---|
| Date | 2016-03-31 06:20 +0200 |
| Subject | [PATCH 9/9] x86 tsc: enumerate BXT tsc_khz via CPUID |
| Message-ID | <riCfp-7Lb-13@gated-at.bofh.it> |
| In reply to | #1367801 |
From: Bin Gao <bin.gao@intel.com>
Hard code the BXT crystal clock (aka ART - Always Running Timer)
to 19.200 MHz, and use CPUID leaf 0x15 to determine the BXT TSC frequency.
Use tsc_khz to sanity check BXT cpu_khz,
which can be erroneous in some configurations.
Signed-off-by: Bin Gao <bin.gao@intel.com>
[lenb: simplified]
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/x86/kernel/tsc.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index ca41c30..64dc998 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -693,7 +693,11 @@ unsigned long native_calibrate_tsc(void)
switch (boot_cpu_data.x86_model) {
case 0x4E: /* SKL */
case 0x5E: /* SKL */
- crystal_khz = 24000; /* 24 MHz */
+ crystal_khz = 24000; /* 24.0 MHz */
+ break;
+ case 0x5C: /* BXT */
+ crystal_khz = 19200; /* 19.2 MHz */
+ break;
}
}
@@ -891,8 +895,12 @@ int recalibrate_cpu_khz(void)
if (cpu_has_tsc) {
cpu_khz = x86_platform.calibrate_cpu();
tsc_khz = x86_platform.calibrate_tsc();
+
if (tsc_khz == 0)
tsc_khz = cpu_khz;
+ else if (abs(cpu_khz - tsc_khz) * 10 > tsc_khz)
+ cpu_khz = tsc_khz;
+
cpu_data(0).loops_per_jiffy =
cpufreq_scale(cpu_data(0).loops_per_jiffy,
cpu_khz_old, cpu_khz);
@@ -1305,8 +1313,16 @@ void __init tsc_init(void)
cpu_khz = x86_platform.calibrate_cpu();
tsc_khz = x86_platform.calibrate_tsc();
+
+ /*
+ * Trust non-zero tsc_khz as authorative,
+ * and use it to sanity check cpu_khz,
+ * which will be off if system timer is off.
+ */
if (tsc_khz == 0)
tsc_khz = cpu_khz;
+ else if (abs(cpu_khz - tsc_khz) * 10 > tsc_khz)
+ cpu_khz = tsc_khz;
if (!tsc_khz) {
mark_tsc_unstable("could not calculate TSC khz");
--
2.8.0.rc4.16.g56331f8
[toc] | [prev] | [next] | [standalone]
| From | Len Brown <lenb@kernel.org> |
|---|---|
| Date | 2016-03-31 06:20 +0200 |
| Subject | [PATCH 4/9] x86 tsc_msr: Correct Silvermont reference clock values |
| Message-ID | <riCfp-7Lb-17@gated-at.bofh.it> |
| In reply to | #1367801 |
From: Len Brown <len.brown@intel.com>
Atom processors use a 19.2 MHz crystal oscillator.
Early processors generate 100 MHz via 19.2 MHz * 26 / 5 = 99.84 MHz.
Later preocessor generate 100 MHz via 19.2 MHz * 125 / 24 = 100 MHz.
Update the Silvermont-based tables accordingly,
matching the Software Developers Manual.
Also, correct a 166 MHz entry that should have been 116 MHz,
and add a missing 80 MHz entry.
Reported-by: Stephane Gasparini <stephane.gasparini@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/x86/kernel/tsc_msr.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c
index 3a866bc..19f2a9a 100644
--- a/arch/x86/kernel/tsc_msr.c
+++ b/arch/x86/kernel/tsc_msr.c
@@ -35,11 +35,11 @@ static struct freq_desc freq_desc_tables[] = {
/* CLV+ */
{ 6, 0x35, 0, { 0, 133200, 0, 0, 0, 99840, 0, 83200 } },
/* TNG - Intel Atom processor Z3400 series */
- { 6, 0x4a, 1, { 0, 99840, 133200, 0, 0, 0, 0, 0 } },
+ { 6, 0x4a, 1, { 0, 100000, 133300, 0, 0, 0, 0, 0 } },
/* VLV2 - Intel Atom processor E3000, Z3600, Z3700 series */
- { 6, 0x37, 1, { 83200, 99840, 133200, 166400, 0, 0, 0, 0 } },
+ { 6, 0x37, 1, { 83300, 100000, 133300, 116700, 80000, 0, 0, 0 } },
/* ANN - Intel Atom processor Z3500 series */
- { 6, 0x5a, 1, { 83200, 99840, 133200, 99840, 0, 0, 0, 0 } },
+ { 6, 0x5a, 1, { 83300, 100000, 133300, 100000, 0, 0, 0, 0 } },
};
static int match_cpu(u8 family, u8 model)
--
2.8.0.rc4.16.g56331f8
[toc] | [prev] | [next] | [standalone]
| From | Len Brown <lenb@kernel.org> |
|---|---|
| Date | 2016-03-31 06:20 +0200 |
| Subject | [PATCH 5/9] x86 tsc_msr: Add Airmont reference clock values |
| Message-ID | <riCfp-7Lb-19@gated-at.bofh.it> |
| In reply to | #1367801 |
From: Len Brown <len.brown@intel.com>
per the Intel 64 and IA-32 Architecture Software Developer's Manual...
Add the reference clock for Intel Atom Processors
Based on the Airmont Microarchitecture.
Reported-by: Stephane Gasparini <stephane.gasparini@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/x86/kernel/tsc_msr.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c
index 19f2a9a..59c371e 100644
--- a/arch/x86/kernel/tsc_msr.c
+++ b/arch/x86/kernel/tsc_msr.c
@@ -13,7 +13,7 @@
#include <asm/apic.h>
#include <asm/param.h>
-#define MAX_NUM_FREQS 8
+#define MAX_NUM_FREQS 9
/*
* If MSR_PERF_STAT[31] is set, the maximum resolved bus ratio can be
@@ -40,6 +40,9 @@ static struct freq_desc freq_desc_tables[] = {
{ 6, 0x37, 1, { 83300, 100000, 133300, 116700, 80000, 0, 0, 0 } },
/* ANN - Intel Atom processor Z3500 series */
{ 6, 0x5a, 1, { 83300, 100000, 133300, 100000, 0, 0, 0, 0 } },
+ /* AMT - Intel Atom processor X7-Z8000 and X5-Z8000 series */
+ { 6, 0x4c, 1, { 83300, 100000, 133300, 116700,
+ 80000, 93300, 90000, 88900, 87500 } },
};
static int match_cpu(u8 family, u8 model)
--
2.8.0.rc4.16.g56331f8
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web