[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 1/2] x86/TSC: don't allow deadline timer to be used with unfixed errata
In preparation of writes to the TSC_ADJUST MSR, avoid the bad interaction of writes to it and the TSC_DEADLINE one. Presumably the original Linux commit bd9240a18e ("x86/apic: Add TSC_DEADLINE quirk due to errata") refers to e.g. KBW092. (Of course this is an issue also without us writing the TSC_ADJUST MSR, if instead firmware did already. The errata checking can't be put in init_apic_mappings() as Linux does, as that runs before we update microcode on the boot CPU. It needs to happen before consumers of tdt_enabled, i.e. - __setup_APIC_LVTT() <- setup_APIC_timer() <- setup_boot_APIC_clock() - <- calibrate_APIC_clock() <- setup_boot_APIC_clock() - setup_boot_APIC_clock() setup_boot_APIC_clock() gets called from smp_prepare_cpus(), which sits after microcode loading (note that calibrate_APIC_clock() gets called before setting tdt_enabled). Also add an MFENCE as per Linux commit 5d7c631d92 ("x86/apic: Serialize LVTT and TSC_DEADLINE writes"), but I see no reason to put a conditional around it. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> --- v2: New. --- a/xen/arch/x86/apic.c +++ b/xen/arch/x86/apic.c @@ -26,6 +26,7 @@ #include <xen/smp.h> #include <xen/softirq.h> #include <asm/mc146818rtc.h> +#include <asm/microcode.h> #include <asm/msr.h> #include <asm/atomic.h> #include <asm/mpspec.h> @@ -1078,6 +1079,13 @@ static void __setup_APIC_LVTT(unsigned i apic_write(APIC_LVTT, lvtt_value); + /* + * See Intel SDM: TSC-Deadline Mode chapter. In xAPIC mode, + * writing to the APIC LVTT and TSC_DEADLINE MSR isn't serialized. + * According to Intel, MFENCE can do the serialization here. + */ + asm volatile( "mfence" : : : "memory" ); + tmp_value = apic_read(APIC_TDCR); apic_write(APIC_TDCR, tmp_value | APIC_TDR_DIV_1); @@ -1092,6 +1100,97 @@ static void setup_APIC_timer(void) local_irq_restore(flags); } +#define DEADLINE_MODEL_MATCH(m, fr) \ + { .vendor = X86_VENDOR_INTEL, .family = 6, .model = (m), \ + .feature = X86_FEATURE_TSC_DEADLINE, \ + .driver_data = (void *)(unsigned long)(fr) } + +static unsigned int __init hsx_deadline_rev(void) +{ + switch ( boot_cpu_data.x86_mask ) + { + case 0x02: return 0x3a; /* EP */ + case 0x04: return 0x0f; /* EX */ + } + + return ~0U; +} + +static unsigned int __init bdx_deadline_rev(void) +{ + switch ( boot_cpu_data.x86_mask ) + { + case 0x02: return 0x00000011; + case 0x03: return 0x0700000e; + case 0x04: return 0x0f00000c; + case 0x05: return 0x0e000003; + } + + return ~0U; +} + +static unsigned int __init skx_deadline_rev(void) +{ + switch ( boot_cpu_data.x86_mask ) + { + case 0x00 ... 0x02: return ~0U; + case 0x03: return 0x01000136; + case 0x04: return 0x02000014; + } + + return 0; +} + +static const struct x86_cpu_id __initconstrel deadline_match[] = { + DEADLINE_MODEL_MATCH(0x3c, 0x22), /* Haswell */ + DEADLINE_MODEL_MATCH(0x3f, hsx_deadline_rev), /* Haswell EP/EX */ + DEADLINE_MODEL_MATCH(0x45, 0x20), /* Haswell D */ + DEADLINE_MODEL_MATCH(0x46, 0x17), /* Haswell H */ + + DEADLINE_MODEL_MATCH(0x3d, 0x25), /* Broadwell */ + DEADLINE_MODEL_MATCH(0x47, 0x17), /* Broadwell H */ + DEADLINE_MODEL_MATCH(0x4f, 0x0b000020), /* Broadwell EP/EX */ + DEADLINE_MODEL_MATCH(0x56, bdx_deadline_rev), /* Broadwell D */ + + DEADLINE_MODEL_MATCH(0x4e, 0xb2), /* Skylake M */ + DEADLINE_MODEL_MATCH(0x55, skx_deadline_rev), /* Skylake X */ + DEADLINE_MODEL_MATCH(0x5e, 0xb2), /* Skylake D */ + + DEADLINE_MODEL_MATCH(0x8e, 0x52), /* Kabylake M */ + DEADLINE_MODEL_MATCH(0x9e, 0x52), /* Kabylake D */ + + {} +}; + +static void __init check_deadline_errata(void) +{ + const struct x86_cpu_id *m; + unsigned int rev; + + if ( boot_cpu_has(X86_FEATURE_HYPERVISOR) ) + return; + + m = x86_match_cpu(deadline_match); + if ( !m ) + return; + + /* + * Function pointers will have the MSB set due to address layout, + * immediate revisions will not. + */ + if ( (long)m->driver_data < 0 ) + rev = ((unsigned int (*)(void))(m->driver_data))(); + else + rev = (unsigned long)m->driver_data; + + if ( this_cpu(ucode_cpu_info).cpu_sig.rev >= rev ) + return; + + setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE); + printk(XENLOG_WARNING "TSC_DEADLINE disabled due to Errata; " + "please update microcode to version %#x (or later)\n", rev); +} + static void wait_tick_pvh(void) { u64 lapse_ns = 1000000000ULL / HZ; @@ -1201,6 +1300,8 @@ void __init setup_boot_APIC_clock(void) apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"); using_apic_timer = true; + check_deadline_errata(); + local_irq_save(flags); calibrate_APIC_clock(); _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |