svn commit: r366909 - in stable/12/sys: amd64/amd64 i386/i386 x86/include x86/x86

Konstantin Belousov kib at FreeBSD.org
Wed Oct 21 15:04:15 UTC 2020


Author: kib
Date: Wed Oct 21 15:04:12 2020
New Revision: 366909
URL: https://svnweb.freebsd.org/changeset/base/366909

Log:
  MFC r366712:
  Limit workaround for errata E400 to appropriate AMD cpus.

Modified:
  stable/12/sys/amd64/amd64/initcpu.c
  stable/12/sys/amd64/amd64/machdep.c
  stable/12/sys/i386/i386/initcpu.c
  stable/12/sys/i386/i386/machdep.c
  stable/12/sys/x86/include/specialreg.h
  stable/12/sys/x86/include/x86_var.h
  stable/12/sys/x86/x86/cpu_machdep.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/amd64/amd64/initcpu.c
==============================================================================
--- stable/12/sys/amd64/amd64/initcpu.c	Wed Oct 21 15:01:33 2020	(r366908)
+++ stable/12/sys/amd64/amd64/initcpu.c	Wed Oct 21 15:04:12 2020	(r366909)
@@ -69,6 +69,23 @@ init_amd(void)
 	uint64_t msr;
 
 	/*
+	 * C1E renders the local APIC timer dead, so we disable it by
+	 * reading the Interrupt Pending Message register and clearing
+	 * both C1eOnCmpHalt (bit 28) and SmiOnCmpHalt (bit 27).
+	 *
+	 * Reference:
+	 *   "BIOS and Kernel Developer's Guide for AMD NPT Family 0Fh Processors"
+	 *   #32559 revision 3.00+
+	 *
+	 * Detect the presence of C1E capability mostly on latest
+	 * dual-cores (or future) k8 family.  Affected models range is
+	 * taken from Linux sources.
+	 */
+	if ((CPUID_TO_FAMILY(cpu_id) == 0xf ||
+	    CPUID_TO_FAMILY(cpu_id) == 0x10) && (cpu_feature2 & CPUID2_HV) == 0)
+		cpu_amdc1e_bug = 1;
+
+	/*
 	 * Work around Erratum 721 for Family 10h and 12h processors.
 	 * These processors may incorrectly update the stack pointer
 	 * after a long series of push and/or near-call instructions,

Modified: stable/12/sys/amd64/amd64/machdep.c
==============================================================================
--- stable/12/sys/amd64/amd64/machdep.c	Wed Oct 21 15:01:33 2020	(r366908)
+++ stable/12/sys/amd64/amd64/machdep.c	Wed Oct 21 15:04:12 2020	(r366909)
@@ -1910,8 +1910,6 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
 	if (env != NULL)
 		strlcpy(kernelname, env, sizeof(kernelname));
 
-	cpu_probe_amdc1e();
-
 #ifdef FDT
 	x86_init_fdt();
 #endif

Modified: stable/12/sys/i386/i386/initcpu.c
==============================================================================
--- stable/12/sys/i386/i386/initcpu.c	Wed Oct 21 15:01:33 2020	(r366908)
+++ stable/12/sys/i386/i386/initcpu.c	Wed Oct 21 15:04:12 2020	(r366909)
@@ -721,8 +721,8 @@ initializecpu(void)
 				break;
 			}
 			break;
-#ifdef CPU_ATHLON_SSE_HACK
 		case CPU_VENDOR_AMD:
+#ifdef CPU_ATHLON_SSE_HACK
 			/*
 			 * Sometimes the BIOS doesn't enable SSE instructions.
 			 * According to AMD document 20734, the mobile
@@ -739,8 +739,16 @@ initializecpu(void)
 				do_cpuid(1, regs);
 				cpu_feature = regs[3];
 			}
-			break;
 #endif
+			/*
+			 * Detect C1E that breaks APIC.  See comment in
+			 * amd64/initcpu.c.
+			 */
+			if ((CPUID_TO_FAMILY(cpu_id) == 0xf ||
+			    CPUID_TO_FAMILY(cpu_id) == 0x10) &&
+			    (cpu_feature2 & CPUID2_HV) == 0)
+				cpu_amdc1e_bug = 1;
+			break;
 		case CPU_VENDOR_CENTAUR:
 			init_via();
 			break;

Modified: stable/12/sys/i386/i386/machdep.c
==============================================================================
--- stable/12/sys/i386/i386/machdep.c	Wed Oct 21 15:01:33 2020	(r366908)
+++ stable/12/sys/i386/i386/machdep.c	Wed Oct 21 15:04:12 2020	(r366909)
@@ -2518,8 +2518,6 @@ init386(int first)
 	thread0.td_pcb->pcb_ext = 0;
 	thread0.td_frame = &proc0_tf;
 
-	cpu_probe_amdc1e();
-
 #ifdef FDT
 	x86_init_fdt();
 #endif

Modified: stable/12/sys/x86/include/specialreg.h
==============================================================================
--- stable/12/sys/x86/include/specialreg.h	Wed Oct 21 15:01:33 2020	(r366908)
+++ stable/12/sys/x86/include/specialreg.h	Wed Oct 21 15:04:12 2020	(r366909)
@@ -1078,6 +1078,7 @@
 #define	MSR_NB_CFG1	0xc001001f	/* NB configuration 1 */
 #define	MSR_K8_UCODE_UPDATE 0xc0010020	/* update microcode */
 #define	MSR_MC0_CTL_MASK 0xc0010044
+#define	MSR_AMDK8_IPM	0xc0010055
 #define	MSR_P_STATE_LIMIT 0xc0010061	/* P-state Current Limit Register */
 #define	MSR_P_STATE_CONTROL 0xc0010062	/* P-state Control Register */
 #define	MSR_P_STATE_STATUS 0xc0010063	/* P-state Status Register */
@@ -1093,6 +1094,9 @@
 
 /* MSR_VM_CR related */
 #define	VM_CR_SVMDIS		0x10	/* SVM: disabled by BIOS */
+
+#define	AMDK8_SMIONCMPHALT	(1ULL << 27)
+#define	AMDK8_C1EONCMPHALT	(1ULL << 28)
 
 /* VIA ACE crypto featureset: for via_feature_rng */
 #define	VIA_HAS_RNG		1	/* cpu has RNG */

Modified: stable/12/sys/x86/include/x86_var.h
==============================================================================
--- stable/12/sys/x86/include/x86_var.h	Wed Oct 21 15:01:33 2020	(r366908)
+++ stable/12/sys/x86/include/x86_var.h	Wed Oct 21 15:04:12 2020	(r366909)
@@ -89,6 +89,7 @@ extern	int	hw_ssb_active;
 extern	int	x86_taa_enable;
 extern	int	cpu_flush_rsb_ctxsw;
 extern	int	x86_rngds_mitg_enable;
+extern	int	cpu_amdc1e_bug;
 
 struct	pcb;
 struct	thread;

Modified: stable/12/sys/x86/x86/cpu_machdep.c
==============================================================================
--- stable/12/sys/x86/x86/cpu_machdep.c	Wed Oct 21 15:01:33 2020	(r366908)
+++ stable/12/sys/x86/x86/cpu_machdep.c	Wed Oct 21 15:04:12 2020	(r366909)
@@ -485,7 +485,9 @@ cpu_mwait_usable(void)
 }
 
 void (*cpu_idle_hook)(sbintime_t) = NULL;	/* ACPI idle hook. */
-static int	cpu_ident_amdc1e = 0;	/* AMD C1E supported. */
+
+int cpu_amdc1e_bug = 0;			/* AMD C1E APIC workaround required. */
+
 static int	idle_mwait = 1;		/* Use MONITOR/MWAIT for short idle. */
 SYSCTL_INT(_machdep, OID_AUTO, idle_mwait, CTLFLAG_RWTUN, &idle_mwait,
     0, "Use MONITOR/MWAIT for short idle");
@@ -586,35 +588,6 @@ cpu_idle_spin(sbintime_t sbt)
 	}
 }
 
-/*
- * C1E renders the local APIC timer dead, so we disable it by
- * reading the Interrupt Pending Message register and clearing
- * both C1eOnCmpHalt (bit 28) and SmiOnCmpHalt (bit 27).
- * 
- * Reference:
- *   "BIOS and Kernel Developer's Guide for AMD NPT Family 0Fh Processors"
- *   #32559 revision 3.00+
- */
-#define	MSR_AMDK8_IPM		0xc0010055
-#define	AMDK8_SMIONCMPHALT	(1ULL << 27)
-#define	AMDK8_C1EONCMPHALT	(1ULL << 28)
-#define	AMDK8_CMPHALT		(AMDK8_SMIONCMPHALT | AMDK8_C1EONCMPHALT)
-
-void
-cpu_probe_amdc1e(void)
-{
-
-	/*
-	 * Detect the presence of C1E capability mostly on latest
-	 * dual-cores (or future) k8 family.
-	 */
-	if (cpu_vendor_id == CPU_VENDOR_AMD &&
-	    (cpu_id & 0x00000f00) == 0x00000f00 &&
-	    (cpu_id & 0x0fff0000) >=  0x00040000) {
-		cpu_ident_amdc1e = 1;
-	}
-}
-
 void (*cpu_idle_fn)(sbintime_t) = cpu_idle_acpi;
 
 void
@@ -644,10 +617,11 @@ cpu_idle(int busy)
 	}
 
 	/* Apply AMD APIC timer C1E workaround. */
-	if (cpu_ident_amdc1e && cpu_disable_c3_sleep) {
+	if (cpu_amdc1e_bug && cpu_disable_c3_sleep) {
 		msr = rdmsr(MSR_AMDK8_IPM);
-		if (msr & AMDK8_CMPHALT)
-			wrmsr(MSR_AMDK8_IPM, msr & ~AMDK8_CMPHALT);
+		if ((msr & (AMDK8_SMIONCMPHALT | AMDK8_C1EONCMPHALT)) != 0)
+			wrmsr(MSR_AMDK8_IPM, msr & ~(AMDK8_SMIONCMPHALT |
+			    AMDK8_C1EONCMPHALT));
 	}
 
 	/* Call main idle method. */


More information about the svn-src-all mailing list