[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.