diff options
| -rw-r--r-- | arch/x86/include/asm/setup.h | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/apic.c | 80 | ||||
| -rw-r--r-- | arch/x86/kernel/hpet.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/time.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/tsc.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/tsc_sync.c | 21 |
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 | ||
| 45 | extern void reserve_standard_io_resources(void); | 45 | extern void reserve_standard_io_resources(void); |
| 46 | extern void i386_reserve_resources(void); | 46 | extern void i386_reserve_resources(void); |
| 47 | extern void setup_default_timer_irq(void); | ||
| 48 | 47 | ||
| 49 | #ifdef CONFIG_X86_INTEL_MID | 48 | #ifdef CONFIG_X86_INTEL_MID |
| 50 | extern void x86_intel_mid_early_setup(void); | 49 | extern 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 | ||
| 58 | unsigned int num_processors; | 60 | unsigned int num_processors; |
| 59 | 61 | ||
| @@ -545,6 +547,81 @@ static struct clock_event_device lapic_clockevent = { | |||
| 545 | }; | 547 | }; |
| 546 | static DEFINE_PER_CPU(struct clock_event_device, lapic_events); | 548 | static 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 | |||
| 556 | static 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 | |||
| 566 | static 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 | |||
| 578 | static 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 | |||
| 600 | static 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 | ||
| 69 | void __init setup_default_timer_irq(void) | 69 | static 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 | ||
