aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
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