aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2017-05-31 11:52:03 -0400
committerThomas Gleixner <tglx@linutronix.de>2017-06-04 15:55:53 -0400
commitbd9240a18edfbfa72e957fc2ba831cf1f13ea073 (patch)
treed3a98afdc40e2c4c071e44751f8f095a4d19a6c3
parentc6e9f42bbeecbc10cd4fbcca474b5859aba1de67 (diff)
x86/apic: Add TSC_DEADLINE quirk due to errata
Due to errata it is possible for the TSC_DEADLINE timer to misbehave after using TSC_ADJUST. A microcode update is available to fix this situation. Avoid using the TSC_DEADLINE timer if it is affected by this issue and report the required microcode version. [ tglx: Renamed function to apic_check_deadline_errata() ] Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: kevin.b.stanton@intel.com Link: http://lkml.kernel.org/r/20170531155306.050849877@infradead.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/x86/kernel/apic/apic.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 87d721a1f3cc..3b215ff36016 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.
@@ -1780,6 +1857,8 @@ void __init init_apic_mappings(void)
1780{ 1857{
1781 unsigned int new_apicid; 1858 unsigned int new_apicid;
1782 1859
1860 apic_check_deadline_errata();
1861
1783 if (x2apic_mode) { 1862 if (x2apic_mode) {
1784 boot_cpu_physical_apicid = read_apic_id(); 1863 boot_cpu_physical_apicid = read_apic_id();
1785 return; 1864 return;