aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2016-06-17 01:22:51 -0400
committerIngo Molnar <mingo@kernel.org>2016-07-11 15:30:13 -0400
commitaa297292d708e89773b3b2cdcaf33f01bfa095d8 (patch)
tree2930daf94d5bba00f8766f2ffcdaf6ba0c8d16ea /arch/x86/kernel
parent02c0cd2dcf7fdc47d054b855b148ea8b82dbb7eb (diff)
x86/tsc: Enumerate SKL cpu_khz and tsc_khz via CPUID
Skylake CPU base-frequency and TSC frequency may differ by up to 2%. Enumerate CPU and TSC frequencies separately, allowing cpu_khz and tsc_khz to differ. The existing CPU frequency calibration mechanism is unchanged. However, CPUID extensions are preferred, when available. CPUID.0x16 is preferred over MSR and timer calibration for CPU frequency discovery. CPUID.0x15 takes precedence over CPU-frequency for TSC frequency discovery. Signed-off-by: Len Brown <len.brown@intel.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/b27ec289fd005833b27d694d9c2dbb716c5cdff7.1466138954.git.len.brown@intel.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/tsc.c75
-rw-r--r--arch/x86/kernel/x86_init.c1
2 files changed, 69 insertions, 7 deletions
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 35a3976c19cc..e1496b79c28a 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -239,7 +239,7 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc)
239 return ns; 239 return ns;
240} 240}
241 241
242static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu) 242static void set_cyc2ns_scale(unsigned long khz, int cpu)
243{ 243{
244 unsigned long long tsc_now, ns_now; 244 unsigned long long tsc_now, ns_now;
245 struct cyc2ns_data *data; 245 struct cyc2ns_data *data;
@@ -248,7 +248,7 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
248 local_irq_save(flags); 248 local_irq_save(flags);
249 sched_clock_idle_sleep_event(); 249 sched_clock_idle_sleep_event();
250 250
251 if (!cpu_khz) 251 if (!khz)
252 goto done; 252 goto done;
253 253
254 data = cyc2ns_write_begin(cpu); 254 data = cyc2ns_write_begin(cpu);
@@ -261,7 +261,7 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
261 * time function is continuous; see the comment near struct 261 * time function is continuous; see the comment near struct
262 * cyc2ns_data. 262 * cyc2ns_data.
263 */ 263 */
264 clocks_calc_mult_shift(&data->cyc2ns_mul, &data->cyc2ns_shift, cpu_khz, 264 clocks_calc_mult_shift(&data->cyc2ns_mul, &data->cyc2ns_shift, khz,
265 NSEC_PER_MSEC, 0); 265 NSEC_PER_MSEC, 0);
266 266
267 /* 267 /*
@@ -665,15 +665,72 @@ success:
665} 665}
666 666
667/** 667/**
668 * native_calibrate_tsc - calibrate the tsc on boot 668 * native_calibrate_tsc
669 * Determine TSC frequency via CPUID, else return 0.
669 */ 670 */
670unsigned long native_calibrate_tsc(void) 671unsigned long native_calibrate_tsc(void)
671{ 672{
673 unsigned int eax_denominator, ebx_numerator, ecx_hz, edx;
674 unsigned int crystal_khz;
675
676 if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
677 return 0;
678
679 if (boot_cpu_data.cpuid_level < 0x15)
680 return 0;
681
682 eax_denominator = ebx_numerator = ecx_hz = edx = 0;
683
684 /* CPUID 15H TSC/Crystal ratio, plus optionally Crystal Hz */
685 cpuid(0x15, &eax_denominator, &ebx_numerator, &ecx_hz, &edx);
686
687 if (ebx_numerator == 0 || eax_denominator == 0)
688 return 0;
689
690 crystal_khz = ecx_hz / 1000;
691
692 if (crystal_khz == 0) {
693 switch (boot_cpu_data.x86_model) {
694 case 0x4E: /* SKL */
695 case 0x5E: /* SKL */
696 crystal_khz = 24000; /* 24 MHz */
697 }
698 }
699
700 return crystal_khz * ebx_numerator / eax_denominator;
701}
702
703static unsigned long cpu_khz_from_cpuid(void)
704{
705 unsigned int eax_base_mhz, ebx_max_mhz, ecx_bus_mhz, edx;
706
707 if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
708 return 0;
709
710 if (boot_cpu_data.cpuid_level < 0x16)
711 return 0;
712
713 eax_base_mhz = ebx_max_mhz = ecx_bus_mhz = edx = 0;
714
715 cpuid(0x16, &eax_base_mhz, &ebx_max_mhz, &ecx_bus_mhz, &edx);
716
717 return eax_base_mhz * 1000;
718}
719
720/**
721 * native_calibrate_cpu - calibrate the cpu on boot
722 */
723unsigned long native_calibrate_cpu(void)
724{
672 u64 tsc1, tsc2, delta, ref1, ref2; 725 u64 tsc1, tsc2, delta, ref1, ref2;
673 unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX; 726 unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX;
674 unsigned long flags, latch, ms, fast_calibrate; 727 unsigned long flags, latch, ms, fast_calibrate;
675 int hpet = is_hpet_enabled(), i, loopmin; 728 int hpet = is_hpet_enabled(), i, loopmin;
676 729
730 fast_calibrate = cpu_khz_from_cpuid();
731 if (fast_calibrate)
732 return fast_calibrate;
733
677 fast_calibrate = cpu_khz_from_msr(); 734 fast_calibrate = cpu_khz_from_msr();
678 if (fast_calibrate) 735 if (fast_calibrate)
679 return fast_calibrate; 736 return fast_calibrate;
@@ -834,8 +891,10 @@ int recalibrate_cpu_khz(void)
834 if (!boot_cpu_has(X86_FEATURE_TSC)) 891 if (!boot_cpu_has(X86_FEATURE_TSC))
835 return -ENODEV; 892 return -ENODEV;
836 893
894 cpu_khz = x86_platform.calibrate_cpu();
837 tsc_khz = x86_platform.calibrate_tsc(); 895 tsc_khz = x86_platform.calibrate_tsc();
838 cpu_khz = tsc_khz; 896 if (tsc_khz == 0)
897 tsc_khz = cpu_khz;
839 cpu_data(0).loops_per_jiffy = cpufreq_scale(cpu_data(0).loops_per_jiffy, 898 cpu_data(0).loops_per_jiffy = cpufreq_scale(cpu_data(0).loops_per_jiffy,
840 cpu_khz_old, cpu_khz); 899 cpu_khz_old, cpu_khz);
841 900
@@ -1241,8 +1300,10 @@ void __init tsc_init(void)
1241 return; 1300 return;
1242 } 1301 }
1243 1302
1303 cpu_khz = x86_platform.calibrate_cpu();
1244 tsc_khz = x86_platform.calibrate_tsc(); 1304 tsc_khz = x86_platform.calibrate_tsc();
1245 cpu_khz = tsc_khz; 1305 if (tsc_khz == 0)
1306 tsc_khz = cpu_khz;
1246 1307
1247 if (!tsc_khz) { 1308 if (!tsc_khz) {
1248 mark_tsc_unstable("could not calculate TSC khz"); 1309 mark_tsc_unstable("could not calculate TSC khz");
@@ -1262,7 +1323,7 @@ void __init tsc_init(void)
1262 */ 1323 */
1263 for_each_possible_cpu(cpu) { 1324 for_each_possible_cpu(cpu) {
1264 cyc2ns_init(cpu); 1325 cyc2ns_init(cpu);
1265 set_cyc2ns_scale(cpu_khz, cpu); 1326 set_cyc2ns_scale(tsc_khz, cpu);
1266 } 1327 }
1267 1328
1268 if (tsc_disabled > 0) 1329 if (tsc_disabled > 0)
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index dad5fe9633a3..58b459296e13 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -92,6 +92,7 @@ static void default_nmi_init(void) { };
92static int default_i8042_detect(void) { return 1; }; 92static int default_i8042_detect(void) { return 1; };
93 93
94struct x86_platform_ops x86_platform = { 94struct x86_platform_ops x86_platform = {
95 .calibrate_cpu = native_calibrate_cpu,
95 .calibrate_tsc = native_calibrate_tsc, 96 .calibrate_tsc = native_calibrate_tsc,
96 .get_wallclock = mach_get_cmos_time, 97 .get_wallclock = mach_get_cmos_time,
97 .set_wallclock = mach_set_rtc_mmss, 98 .set_wallclock = mach_set_rtc_mmss,