|
54 | 54 | #include <asm/mce.h>
|
55 | 55 | #include <asm/tsc.h>
|
56 | 56 | #include <asm/hypervisor.h>
|
| 57 | +#include <asm/cpu_device_id.h> |
| 58 | +#include <asm/intel-family.h> |
57 | 59 |
|
58 | 60 | unsigned int num_processors;
|
59 | 61 |
|
@@ -545,6 +547,81 @@ static struct clock_event_device lapic_clockevent = {
|
545 | 547 | };
|
546 | 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 | 626 | * Setup the local APIC timer for this CPU. Copy the initialized values
|
550 | 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 | 1858 | unsigned int new_apicid;
|
1782 | 1859 |
|
| 1860 | + apic_check_deadline_errata(); |
| 1861 | + |
1783 | 1862 | if (x2apic_mode) {
|
1784 | 1863 | boot_cpu_physical_apicid = read_apic_id();
|
1785 | 1864 | return;
|
|
0 commit comments