[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 1/6] x86/AMD Split init_amd() into per-uarch helpers



This reduces the complexity of init_amd(), and collects related
workarounds together.

It also offers us the opportunity to stop performing workarounds when
virtualised - doing so is wasteful, as it all involves poking MSRs which
no hypervisor will let us touch in practice.

As amd.c has diverged almost entirely from its Linux heratage, start
switching it to using Xen hypervisor style.

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Wei Liu <wei.liu2@xxxxxxxxxx>
CC: Roger Pau Monné <roger.pau@xxxxxxxxxx>

I've dropped various printk()s about working around some errata, because
their use was completely inconsistent.  They want to be uniform, whether
that is missing or present.
---
 xen/arch/x86/cpu/amd.c | 266 ++++++++++++++++++++++++++++---------------------
 1 file changed, 153 insertions(+), 113 deletions(-)

diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index c790416..c3aa1f4 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -534,22 +534,165 @@ static void early_init_amd(struct cpuinfo_x86 *c)
        ctxt_switch_levelling(NULL);
 }
 
+static void init_amd_k8(struct cpuinfo_x86 *c)
+{
+    uint64_t val;
+
+    /*
+     * Skip errata workarounds if we are virtualised.  We won't have
+     * sufficient control of hardware to do anything useful.
+     */
+    if ( !cpu_has_hypervisor )
+        return;
+
+    /*
+     * Disable TLB flush filter by setting HWCR.FFDIS bit 6
+     *
+     * Erratum 63 for SH-B3 steppings
+     * Erratum 122 for all steppings (F+ have it disabled by default)
+     */
+    rdmsrl(MSR_K7_HWCR, val);
+    if ( !(val & (1u << 6)) )
+        wrmsrl(MSR_K7_HWCR, val | (1u << 6));
+
+    /*
+     * Some BIOSes incorrectly force LAHF_LM, but only revisions D and later
+     * actually support it.
+     *
+     * AMD Erratum #110, docId: 25759.
+     */
+    if ( c->x86_model < 0x14 && cpu_has(c, X86_FEATURE_LAHF_LM) )
+    {
+        unsigned int l, h;
+
+        __clear_bit(X86_FEATURE_LAHF_LM, c->x86_capability);
+        if ( !rdmsr_amd_safe(0xc001100d, &l, &h) )
+            wrmsr_amd_safe(0xc001100d, l,
+                           h & ~cpufeat_mask(X86_FEATURE_LAHF_LM));
+    }
+}
+
+static void init_amd_k10(struct cpuinfo_x86 *c)
+{
+    uint64_t val;
+
+    /* Pointless to use MWAIT on Family10 as it does not deep sleep. */
+    __clear_bit(X86_FEATURE_MONITOR, c->x86_capability);
+
+    /*
+     * Skip errata workarounds if we are virtualised.  We won't have
+     * sufficient control of hardware to do anything useful.
+     */
+    if ( !cpu_has_hypervisor )
+        return;
+
+    if ( c == &boot_cpu_data )
+        check_enable_amd_mmconf_dmi();
+    fam10h_check_enable_mmcfg();
+
+    /*
+     * On family 10h BIOS may not have properly enabled WC+ support, causing
+     * it to be converted to CD memtype.  This may result in performance
+     * degradation for certain nested-paging guests.  Prevent this conversion
+     * by clearing bit 24 in MSR_F10_BU_CFG2.
+     */
+    rdmsrl(MSR_F10_BU_CFG2, val);
+    if ( val & (1ul << 24) )
+        wrmsrl(MSR_F10_BU_CFG2, val & ~(1ul << 24));
+}
+
+static void init_amd_lynx(struct cpuinfo_x86 *c) /* Fam 12h */
+{
+    uint64_t val;
+
+    /*
+     * Skip errata workarounds if we are virtualised.  We won't have
+     * sufficient control of hardware to do anything useful.
+     */
+    if ( !cpu_has_hypervisor )
+        return;
+
+    /* Erratum 665 - Integer divide may cause unpredictable system behaviour. 
*/
+    rdmsrl(MSR_AMD64_DE_CFG, val);
+    if ( !(val & (1u << 31)) )
+        wrmsrl(MSR_AMD64_DE_CFG, val | (1u << 31));
+}
+
+static void init_amd_bulldozer(struct cpuinfo_x86 *c) /* Fam 15h */
+{
+    uint64_t val;
+
+    /*
+     * Skip errata workarounds if we are virtualised.  We won't have
+     * sufficient control of hardware to do anything useful.
+     */
+    if ( !cpu_has_hypervisor )
+        return;
+
+    /* re-enable TopologyExtensions if switched off by BIOS */
+    if ( c->x86_model >= 0x10 && c->x86_model <= 0x1f &&
+         !cpu_has(c, X86_FEATURE_TOPOEXT) &&
+         !rdmsr_safe(MSR_K8_EXT_FEATURE_MASK, val) )
+    {
+        __set_bit(X86_FEATURE_TOPOEXT, c->x86_capability);
+        wrmsr_safe(MSR_K8_EXT_FEATURE_MASK, val | (1ull << 54));
+    }
+
+    /*
+     * The way access filter has a performance penalty on some workloads.
+     * Disable it on the affected CPUs.
+     */
+    if ( c->x86_model >= 0x02 && c->x86_model < 0x20 &&
+         !rdmsr_safe(MSR_AMD64_IC_CFG, val) && (val & 0x1e) != 0x1e )
+        wrmsr_safe(MSR_AMD64_IC_CFG, val | 0x1e);
+}
+
+static void init_amd_jaguar(struct cpuinfo_x86 *c) /* Fam 16h */
+{
+    uint64_t val;
+
+    /*
+     * Skip errata workarounds if we are virtualised.  We won't have
+     * sufficient control of hardware to do anything useful.
+     */
+    if ( !cpu_has_hypervisor )
+        return;
+
+    if ( c->x86_model <= 0xf )
+    {
+        /* Erratum #792. */
+        if ( c == &boot_cpu_data )
+        {
+            unsigned int l = pci_conf_read32(0, 0, 0x18, 0x3, 0x58);
+            unsigned int h = pci_conf_read32(0, 0, 0x18, 0x3, 0x5c);
+
+            if ( l & 0x1f )
+                pci_conf_write32(0, 0, 0x18, 0x3, 0x58, l & ~0x1f);
+
+            if ( h & 0x1 )
+                pci_conf_write32(0, 0, 0x18, 0x3, 0x5c, h & ~0x1);
+        }
+
+        /* Erratum #793. */
+        rdmsrl(MSR_AMD64_LS_CFG, val);
+        if ( !(val & (1 << 15)) )
+            wrmsrl(MSR_AMD64_LS_CFG, val | (1 << 15));
+    }
+}
+
 static void init_amd(struct cpuinfo_x86 *c)
 {
        u32 l, h;
 
        unsigned long long value;
 
-       /* Disable TLB flush filter by setting HWCR.FFDIS on K8
-        * bit 6 of msr C001_0015
-        *
-        * Errata 63 for SH-B3 steppings
-        * Errata 122 for all steppings (F+ have it disabled by default)
-        */
-       if (c->x86 == 15) {
-               rdmsrl(MSR_K7_HWCR, value);
-               value |= 1 << 6;
-               wrmsrl(MSR_K7_HWCR, value);
+       switch ( c->x86 )
+       {
+       case 0xf:  init_amd_k8(c); break;
+       case 0x10: init_amd_k10(c); break;
+       case 0x12: init_amd_lynx(c); break;
+       case 0x15: init_amd_bulldozer(c); break;
+       case 0x16: init_amd_jaguar(c); break;
        }
 
        /*
@@ -558,18 +701,6 @@ static void init_amd(struct cpuinfo_x86 *c)
         * alias, leaving 3DNow in the extended leaf.
         */
        __clear_bit(X86_FEATURE_PBE, c->x86_capability);
-       
-       if (c->x86 == 0xf && c->x86_model < 0x14
-           && cpu_has(c, X86_FEATURE_LAHF_LM)) {
-               /*
-                * Some BIOSes incorrectly force this feature, but only K8
-                * revision D (model = 0x14) and later actually support it.
-                * (AMD Erratum #110, docId: 25759).
-                */
-               __clear_bit(X86_FEATURE_LAHF_LM, c->x86_capability);
-               if (!rdmsr_amd_safe(0xc001100d, &l, &h))
-                       wrmsr_amd_safe(0xc001100d, l, h & ~1);
-       }
 
        /*
         * Attempt to set lfence to be Dispatch Serialising.  This MSR almost
@@ -651,35 +782,8 @@ static void init_amd(struct cpuinfo_x86 *c)
                }
        }
 
-       /* re-enable TopologyExtensions if switched off by BIOS */
-       if ((c->x86 == 0x15) &&
-           (c->x86_model >= 0x10) && (c->x86_model <= 0x1f) &&
-           !cpu_has(c, X86_FEATURE_TOPOEXT) &&
-           !rdmsr_safe(MSR_K8_EXT_FEATURE_MASK, value)) {
-               value |= 1ULL << 54;
-               wrmsr_safe(MSR_K8_EXT_FEATURE_MASK, value);
-               rdmsrl(MSR_K8_EXT_FEATURE_MASK, value);
-               if (value & (1ULL << 54)) {
-                       __set_bit(X86_FEATURE_TOPOEXT, c->x86_capability);
-                       printk(KERN_INFO "CPU: Re-enabling disabled "
-                              "Topology Extensions Support\n");
-               }
-       }
-
-       /*
-        * The way access filter has a performance penalty on some workloads.
-        * Disable it on the affected CPUs.
-        */
-       if (c->x86 == 0x15 && c->x86_model >= 0x02 && c->x86_model < 0x20 &&
-           !rdmsr_safe(MSR_AMD64_IC_CFG, value) && (value & 0x1e) != 0x1e)
-               wrmsr_safe(MSR_AMD64_IC_CFG, value | 0x1e);
-
         amd_get_topology(c);
 
-       /* Pointless to use MWAIT on Family10 as it does not deep sleep. */
-       if (c->x86 == 0x10)
-               __clear_bit(X86_FEATURE_MONITOR, c->x86_capability);
-
        if (!cpu_has_amd_erratum(c, AMD_ERRATUM_121))
                opt_allow_unsafe = 1;
        else if (opt_allow_unsafe < 0)
@@ -694,73 +798,9 @@ static void init_amd(struct cpuinfo_x86 *c)
                       "*** Pass \"allow_unsafe\" if you're trusting"
                       " all your (PV) guest kernels. ***\n");
 
-       if (c->x86 == 0x16 && c->x86_model <= 0xf) {
-               if (c == &boot_cpu_data) {
-                       l = pci_conf_read32(0, 0, 0x18, 0x3, 0x58);
-                       h = pci_conf_read32(0, 0, 0x18, 0x3, 0x5c);
-                       if ((l & 0x1f) | (h & 0x1))
-                               printk(KERN_WARNING
-                                      "Applying workaround for erratum 792: 
%s%s%s\n",
-                                      (l & 0x1f) ? "clearing D18F3x58[4:0]" : 
"",
-                                      ((l & 0x1f) && (h & 0x1)) ? " and " : "",
-                                      (h & 0x1) ? "clearing D18F3x5C[0]" : "");
-
-                       if (l & 0x1f)
-                               pci_conf_write32(0, 0, 0x18, 0x3, 0x58,
-                                                l & ~0x1f);
-
-                       if (h & 0x1)
-                               pci_conf_write32(0, 0, 0x18, 0x3, 0x5c,
-                                                h & ~0x1);
-               }
-
-               rdmsrl(MSR_AMD64_LS_CFG, value);
-               if (!(value & (1 << 15))) {
-                       static bool_t warned;
-
-                       if (c == &boot_cpu_data || opt_cpu_info ||
-                           !test_and_set_bool(warned))
-                               printk(KERN_WARNING
-                                      "CPU%u: Applying workaround for erratum 
793\n",
-                                      smp_processor_id());
-                       wrmsrl(MSR_AMD64_LS_CFG, value | (1 << 15));
-               }
-       } else if (c->x86 == 0x12) {
-               rdmsrl(MSR_AMD64_DE_CFG, value);
-               if (!(value & (1U << 31))) {
-                       static bool warned;
-
-                       if (c == &boot_cpu_data || opt_cpu_info ||
-                           !test_and_set_bool(warned))
-                               printk(KERN_WARNING
-                                      "CPU%u: Applying workaround for erratum 
665\n",
-                                      smp_processor_id());
-                       wrmsrl(MSR_AMD64_DE_CFG, value | (1U << 31));
-               }
-       }
-
        /* AMD CPUs do not support SYSENTER outside of legacy mode. */
        __clear_bit(X86_FEATURE_SEP, c->x86_capability);
 
-       if (c->x86 == 0x10) {
-               /* do this for boot cpu */
-               if (c == &boot_cpu_data)
-                       check_enable_amd_mmconf_dmi();
-
-               fam10h_check_enable_mmcfg();
-
-               /*
-                * On family 10h BIOS may not have properly enabled WC+
-                * support, causing it to be converted to CD memtype. This may
-                * result in performance degradation for certain nested-paging
-                * guests. Prevent this conversion by clearing bit 24 in
-                * MSR_F10_BU_CFG2.
-                */
-               rdmsrl(MSR_F10_BU_CFG2, value);
-               value &= ~(1ULL << 24);
-               wrmsrl(MSR_F10_BU_CFG2, value);
-       }
-
        /*
         * Family 0x12 and above processors have APIC timer
         * running in deep C states.
-- 
2.1.4


_______________________________________________
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®.