Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/x86/x86 On certain AMD f10h CPUs (like mine), the B...



details:   https://anonhg.NetBSD.org/src/rev/d56bfc9e50fa
branches:  trunk
changeset: 838367:d56bfc9e50fa
user:      maxv <maxv%NetBSD.org@localhost>
date:      Sun Jan 13 12:16:58 2019 +0000

description:
On certain AMD f10h CPUs (like mine), the BIOS does not enable WC+. It
means that the guest pages that are WC+ become CD, and this degrades
performance of the guests.

Explicitly enable WC+.

While here clarify the AMD identification code.

diffstat:

 sys/arch/x86/x86/identcpu.c |  63 +++++++++++++++++++++++++-------------------
 1 files changed, 36 insertions(+), 27 deletions(-)

diffs (103 lines):

diff -r 56bc6e58788f -r d56bfc9e50fa sys/arch/x86/x86/identcpu.c
--- a/sys/arch/x86/x86/identcpu.c       Sun Jan 13 11:03:20 2019 +0000
+++ b/sys/arch/x86/x86/identcpu.c       Sun Jan 13 12:16:58 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: identcpu.c,v 1.85 2019/01/06 16:13:51 maxv Exp $       */
+/*     $NetBSD: identcpu.c,v 1.86 2019/01/13 12:16:58 maxv Exp $       */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.85 2019/01/06 16:13:51 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.86 2019/01/13 12:16:58 maxv Exp $");
 
 #include "opt_xen.h"
 
@@ -354,41 +354,51 @@
 }
 
 static void
-cpu_probe_k5(struct cpu_info *ci)
+cpu_probe_amd(struct cpu_info *ci)
 {
+       uint64_t val;
        int flag;
 
-       if (cpu_vendor != CPUVENDOR_AMD ||
-           CPUID_TO_FAMILY(ci->ci_signature) != 5)
+       if (cpu_vendor != CPUVENDOR_AMD)
+               return;
+       if (CPUID_TO_FAMILY(ci->ci_signature) < 5)
                return;
 
-       if (CPUID_TO_MODEL(ci->ci_signature) == 0) {
+       switch (CPUID_TO_FAMILY(ci->ci_signature)) {
+       case 0x05: /* K5 */
+               if (CPUID_TO_MODEL(ci->ci_signature) == 0) {
+                       /*
+                        * According to the AMD Processor Recognition App Note,
+                        * the AMD-K5 Model 0 uses the wrong bit to indicate
+                        * support for global PTEs, instead using bit 9 (APIC)
+                        * rather than bit 13 (i.e. "0x200" vs. 0x2000").
+                        */
+                       flag = ci->ci_feat_val[0];
+                       if ((flag & CPUID_APIC) != 0)
+                               flag = (flag & ~CPUID_APIC) | CPUID_PGE;
+                       ci->ci_feat_val[0] = flag;
+               }
+               break;
+
+       case 0x10: /* Family 10h */
                /*
-                * According to the AMD Processor Recognition App Note,
-                * the AMD-K5 Model 0 uses the wrong bit to indicate
-                * support for global PTEs, instead using bit 9 (APIC)
-                * rather than bit 13 (i.e. "0x200" vs. 0x2000".  Oops!).
+                * On Family 10h, certain BIOSes do not enable WC+ support.
+                * This causes WC+ to become CD, and degrades guest
+                * performance at the NPT level.
+                *
+                * Explicitly enable WC+ if we're not a guest.
                 */
-               flag = ci->ci_feat_val[0];
-               if ((flag & CPUID_APIC) != 0)
-                       flag = (flag & ~CPUID_APIC) | CPUID_PGE;
-               ci->ci_feat_val[0] = flag;
+               if (!ISSET(ci->ci_feat_val[1], CPUID2_RAZ)) {
+                       val = rdmsr(MSR_BU_CFG2);
+                       val &= ~BU_CFG2_CWPLUS_DIS;
+                       wrmsr(MSR_BU_CFG2, val);
+               }
+               break;
        }
 
        cpu_probe_amd_cache(ci);
 }
 
-static void
-cpu_probe_k678(struct cpu_info *ci)
-{
-
-       if (cpu_vendor != CPUVENDOR_AMD ||
-           CPUID_TO_FAMILY(ci->ci_signature) < 6)
-               return;
-
-       cpu_probe_amd_cache(ci);
-}
-
 static inline uint8_t
 cyrix_read_reg(uint8_t reg)
 {
@@ -956,8 +966,7 @@
        }
 
        cpu_probe_intel(ci);
-       cpu_probe_k5(ci);
-       cpu_probe_k678(ci);
+       cpu_probe_amd(ci);
        cpu_probe_cyrix(ci);
        cpu_probe_winchip(ci);
        cpu_probe_c3(ci);



Home | Main Index | Thread Index | Old Index