Module Name:    src
Committed By:   maxv
Date:           Sun Jan 13 12:16:58 UTC 2019

Modified Files:
        src/sys/arch/x86/x86: identcpu.c

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.85 -r1.86 src/sys/arch/x86/x86/identcpu.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/x86/x86/identcpu.c
diff -u src/sys/arch/x86/x86/identcpu.c:1.85 src/sys/arch/x86/x86/identcpu.c:1.86
--- src/sys/arch/x86/x86/identcpu.c:1.85	Sun Jan  6 16:13:51 2019
+++ src/sys/arch/x86/x86/identcpu.c	Sun Jan 13 12:16:58 2019
@@ -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 @@ cpu_probe_amd_cache(struct cpu_info *ci)
 }
 
 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(struct cpu_info *ci)
 	}
 
 	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);

Reply via email to