aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-03 21:01:50 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-03 21:01:50 -0400
commit3ad918e65d6926490c8f18a157cea25bf29ecd3a (patch)
treeb8d2a5a0c4be33eca5cfd528a4f8add1d0005aea
parent8c073517a992124e385040c0da0df809abfa8f61 (diff)
parenta1272dd5531b259bf7313ac7597a67362698038c (diff)
Merge branch 'x86-timers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 timers updates from Thomas Gleixner: "This update contains: - The solution for the TSC deadline timer borkage, which is caused by a hardware problem in the TSC_ADJUST/TSC_DEADLINE_TIMER logic. The problem is documented now and fixed with a microcode update, so we can remove the workaround and just check for the microcode version. If the microcode is not up to date, then the TSC deadline timer is disabled. If the borkage is fixed by the proper microcode version, then the deadline timer can be used. In both cases the restrictions to the range of the TSC_ADJUST value, which were added as workarounds, are removed. - A few simple fixes and updates to the timer related x86 code" * 'x86-timers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/tsc: Call check_system_tsc_reliable() before unsynchronized_tsc() x86/hpet: Do not use smp_processor_id() in preemptible code x86/time: Make setup_default_timer_irq() static x86/tsc: Remove the TSC_ADJUST clamp x86/apic: Add TSC_DEADLINE quirk due to errata x86/apic: Change the lapic name in deadline mode
-rw-r--r--arch/x86/include/asm/setup.h1
-rw-r--r--arch/x86/kernel/apic/apic.c80
-rw-r--r--arch/x86/kernel/hpet.c2
-rw-r--r--arch/x86/kernel/time.c2
-rw-r--r--arch/x86/kernel/tsc.c4
-rw-r--r--arch/x86/kernel/tsc_sync.c21
6 files changed, 85 insertions, 25 deletions
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index ac1d5da14734..e4585a393965 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -44,7 +44,6 @@ extern unsigned long saved_video_mode;
44 44
45extern void reserve_standard_io_resources(void); 45extern void reserve_standard_io_resources(void);
46extern void i386_reserve_resources(void); 46extern void i386_reserve_resources(void);
47extern void setup_default_timer_irq(void);
48 47
49#ifdef CONFIG_X86_INTEL_MID 48#ifdef CONFIG_X86_INTEL_MID
50extern void x86_intel_mid_early_setup(void); 49extern void x86_intel_mid_early_setup(void);
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index e7409468efc6..98b3dd8cf2bf 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -54,6 +54,8 @@
54#include <asm/mce.h> 54#include <asm/mce.h>
55#include <asm/tsc.h> 55#include <asm/tsc.h>
56#include <asm/hypervisor.h> 56#include <asm/hypervisor.h>
57#include <asm/cpu_device_id.h>
58#include <asm/intel-family.h>
57 59
58unsigned int num_processors; 60unsigned int num_processors;
59 61
@@ -545,6 +547,81 @@ static struct clock_event_device lapic_clockevent = {
545}; 547};
546static DEFINE_PER_CPU(struct clock_event_device, lapic_events); 548static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
547 549
550#define DEADLINE_MODEL_MATCH_FUNC(model, func) \
551 { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&func }
552
553#define DEADLINE_MODEL_MATCH_REV(model, rev) \
554 { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)rev }
555
556static u32 hsx_deadline_rev(void)
557{
558 switch (boot_cpu_data.x86_mask) {
559 case 0x02: return 0x3a; /* EP */
560 case 0x04: return 0x0f; /* EX */
561 }
562
563 return ~0U;
564}
565
566static u32 bdx_deadline_rev(void)
567{
568 switch (boot_cpu_data.x86_mask) {
569 case 0x02: return 0x00000011;
570 case 0x03: return 0x0700000e;
571 case 0x04: return 0x0f00000c;
572 case 0x05: return 0x0e000003;
573 }
574
575 return ~0U;
576}
577
578static const struct x86_cpu_id deadline_match[] = {
579 DEADLINE_MODEL_MATCH_FUNC( INTEL_FAM6_HASWELL_X, hsx_deadline_rev),
580 DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_BROADWELL_X, 0x0b000020),
581 DEADLINE_MODEL_MATCH_FUNC( INTEL_FAM6_BROADWELL_XEON_D, bdx_deadline_rev),
582 DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_SKYLAKE_X, 0x02000014),
583
584 DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_HASWELL_CORE, 0x22),
585 DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_HASWELL_ULT, 0x20),
586 DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_HASWELL_GT3E, 0x17),
587
588 DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_BROADWELL_CORE, 0x25),
589 DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_BROADWELL_GT3E, 0x17),
590
591 DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_SKYLAKE_MOBILE, 0xb2),
592 DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_SKYLAKE_DESKTOP, 0xb2),
593
594 DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_KABYLAKE_MOBILE, 0x52),
595 DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_KABYLAKE_DESKTOP, 0x52),
596
597 {},
598};
599
600static void apic_check_deadline_errata(void)
601{
602 const struct x86_cpu_id *m = x86_match_cpu(deadline_match);
603 u32 rev;
604
605 if (!m)
606 return;
607
608 /*
609 * Function pointers will have the MSB set due to address layout,
610 * immediate revisions will not.
611 */
612 if ((long)m->driver_data < 0)
613 rev = ((u32 (*)(void))(m->driver_data))();
614 else
615 rev = (u32)m->driver_data;
616
617 if (boot_cpu_data.microcode >= rev)
618 return;
619
620 setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
621 pr_err(FW_BUG "TSC_DEADLINE disabled due to Errata; "
622 "please update microcode to version: 0x%x (or later)\n", rev);
623}
624
548/* 625/*
549 * Setup the local APIC timer for this CPU. Copy the initialized values 626 * Setup the local APIC timer for this CPU. Copy the initialized values
550 * of the boot CPU and register the clock event in the framework. 627 * of the boot CPU and register the clock event in the framework.
@@ -563,6 +640,7 @@ static void setup_APIC_timer(void)
563 levt->cpumask = cpumask_of(smp_processor_id()); 640 levt->cpumask = cpumask_of(smp_processor_id());
564 641
565 if (this_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) { 642 if (this_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) {
643 levt->name = "lapic-deadline";
566 levt->features &= ~(CLOCK_EVT_FEAT_PERIODIC | 644 levt->features &= ~(CLOCK_EVT_FEAT_PERIODIC |
567 CLOCK_EVT_FEAT_DUMMY); 645 CLOCK_EVT_FEAT_DUMMY);
568 levt->set_next_event = lapic_next_deadline; 646 levt->set_next_event = lapic_next_deadline;
@@ -1779,6 +1857,8 @@ void __init init_apic_mappings(void)
1779{ 1857{
1780 unsigned int new_apicid; 1858 unsigned int new_apicid;
1781 1859
1860 apic_check_deadline_errata();
1861
1782 if (x2apic_mode) { 1862 if (x2apic_mode) {
1783 boot_cpu_physical_apicid = read_apic_id(); 1863 boot_cpu_physical_apicid = read_apic_id();
1784 return; 1864 return;
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 89ff7af2de50..16f82a3aaec7 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -285,7 +285,7 @@ static void hpet_legacy_clockevent_register(void)
285 * Start hpet with the boot cpu mask and make it 285 * Start hpet with the boot cpu mask and make it
286 * global after the IO_APIC has been initialized. 286 * global after the IO_APIC has been initialized.
287 */ 287 */
288 hpet_clockevent.cpumask = cpumask_of(smp_processor_id()); 288 hpet_clockevent.cpumask = cpumask_of(boot_cpu_data.cpu_index);
289 clockevents_config_and_register(&hpet_clockevent, hpet_freq, 289 clockevents_config_and_register(&hpet_clockevent, hpet_freq,
290 HPET_MIN_PROG_DELTA, 0x7FFFFFFF); 290 HPET_MIN_PROG_DELTA, 0x7FFFFFFF);
291 global_clock_event = &hpet_clockevent; 291 global_clock_event = &hpet_clockevent;
diff --git a/arch/x86/kernel/time.c b/arch/x86/kernel/time.c
index d39c09119db6..e0754cdbad37 100644
--- a/arch/x86/kernel/time.c
+++ b/arch/x86/kernel/time.c
@@ -66,7 +66,7 @@ static struct irqaction irq0 = {
66 .name = "timer" 66 .name = "timer"
67}; 67};
68 68
69void __init setup_default_timer_irq(void) 69static void __init setup_default_timer_irq(void)
70{ 70{
71 if (!nr_legacy_irqs()) 71 if (!nr_legacy_irqs())
72 return; 72 return;
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 5270fc0c2df6..796d96bb0821 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -1328,11 +1328,11 @@ void __init tsc_init(void)
1328 1328
1329 use_tsc_delay(); 1329 use_tsc_delay();
1330 1330
1331 check_system_tsc_reliable();
1332
1331 if (unsynchronized_tsc()) 1333 if (unsynchronized_tsc())
1332 mark_tsc_unstable("TSCs unsynchronized"); 1334 mark_tsc_unstable("TSCs unsynchronized");
1333 1335
1334 check_system_tsc_reliable();
1335
1336 detect_art(); 1336 detect_art();
1337} 1337}
1338 1338
diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c
index 728f75378475..7842371bc9e4 100644
--- a/arch/x86/kernel/tsc_sync.c
+++ b/arch/x86/kernel/tsc_sync.c
@@ -71,13 +71,8 @@ static void tsc_sanitize_first_cpu(struct tsc_adjust *cur, s64 bootval,
71 * non zero. We don't do that on non boot cpus because physical 71 * non zero. We don't do that on non boot cpus because physical
72 * hotplug should have set the ADJUST register to a value > 0 so 72 * hotplug should have set the ADJUST register to a value > 0 so
73 * the TSC is in sync with the already running cpus. 73 * the TSC is in sync with the already running cpus.
74 *
75 * But we always force positive ADJUST values. Otherwise the TSC
76 * deadline timer creates an interrupt storm. We also have to
77 * prevent values > 0x7FFFFFFF as those wreckage the timer as well.
78 */ 74 */
79 if ((bootcpu && bootval != 0) || (!bootcpu && bootval < 0) || 75 if (bootcpu && bootval != 0) {
80 (bootval > 0x7FFFFFFF)) {
81 pr_warn(FW_BUG "TSC ADJUST: CPU%u: %lld force to 0\n", cpu, 76 pr_warn(FW_BUG "TSC ADJUST: CPU%u: %lld force to 0\n", cpu,
82 bootval); 77 bootval);
83 wrmsrl(MSR_IA32_TSC_ADJUST, 0); 78 wrmsrl(MSR_IA32_TSC_ADJUST, 0);
@@ -451,20 +446,6 @@ retry:
451 */ 446 */
452 cur->adjusted += cur_max_warp; 447 cur->adjusted += cur_max_warp;
453 448
454 /*
455 * TSC deadline timer stops working or creates an interrupt storm
456 * with adjust values < 0 and > x07ffffff.
457 *
458 * To allow adjust values > 0x7FFFFFFF we need to disable the
459 * deadline timer and use the local APIC timer, but that requires
460 * more intrusive changes and we do not have any useful information
461 * from Intel about the underlying HW wreckage yet.
462 */
463 if (cur->adjusted < 0)
464 cur->adjusted = 0;
465 if (cur->adjusted > 0x7FFFFFFF)
466 cur->adjusted = 0x7FFFFFFF;
467
468 pr_warn("TSC ADJUST compensate: CPU%u observed %lld warp. Adjust: %lld\n", 449 pr_warn("TSC ADJUST compensate: CPU%u observed %lld warp. Adjust: %lld\n",
469 cpu, cur_max_warp, cur->adjusted); 450 cpu, cur_max_warp, cur->adjusted);
470 451