svn commit: r220018 - in head/sys: amd64/amd64 i386/i386

Jung-uk Kim jkim at FreeBSD.org
Sat Mar 26 02:02:07 UTC 2011


Author: jkim
Date: Sat Mar 26 02:02:07 2011
New Revision: 220018
URL: http://svn.freebsd.org/changeset/base/220018

Log:
  Improve CPU identifications of various IDT/Centaur/VIA, Rise and Transmeta
  CPUs.  These CPUs need explicit MSR configuration to expose ceratin CPU
  capabilities (e.g., CMPXCHG8B) to work around compatibility issues with
  ancient software.  Unfortunately, Rise mP6 does not set the CX8 bit in CPUID
  and there is no MSR to expose the feature although all mP6 processors are
  capable of CMPXCHG8B according to datasheets I found from the Net.  Clean up
  and simplify VIA PadLock detection while I am in the neighborhood.

Modified:
  head/sys/amd64/amd64/identcpu.c
  head/sys/amd64/amd64/initcpu.c
  head/sys/i386/i386/identcpu.c
  head/sys/i386/i386/initcpu.c

Modified: head/sys/amd64/amd64/identcpu.c
==============================================================================
--- head/sys/amd64/amd64/identcpu.c	Sat Mar 26 01:24:55 2011	(r220017)
+++ head/sys/amd64/amd64/identcpu.c	Sat Mar 26 02:02:07 2011	(r220018)
@@ -385,7 +385,7 @@ printcpuinfo(void)
 				);
 			}
 
-			if (cpu_vendor_id == CPU_VENDOR_CENTAUR)
+			if (via_feature_rng != 0 || via_feature_xcrypt != 0)
 				print_via_padlock_info();
 
 			if ((cpu_feature & CPUID_HTT) &&
@@ -643,25 +643,7 @@ print_via_padlock_info(void)
 {
 	u_int regs[4];
 
-	/* Check for supported models. */
-	switch (cpu_id & 0xff0) {
-	case 0x690:
-		if ((cpu_id & 0xf) < 3)
-			return;
-	case 0x6a0:
-	case 0x6d0:
-	case 0x6f0:
-		break;
-	default:
-		return;
-	}
-	
-	do_cpuid(0xc0000000, regs);
-	if (regs[0] >= 0xc0000001)
-		do_cpuid(0xc0000001, regs);
-	else
-		return;
-
+	do_cpuid(0xc0000001, regs);
 	printf("\n  VIA Padlock Features=0x%b", regs[3],
 	"\020"
 	"\003RNG"		/* RNG */

Modified: head/sys/amd64/amd64/initcpu.c
==============================================================================
--- head/sys/amd64/amd64/initcpu.c	Sat Mar 26 01:24:55 2011	(r220017)
+++ head/sys/amd64/amd64/initcpu.c	Sat Mar 26 02:02:07 2011	(r220018)
@@ -74,72 +74,47 @@ u_int	cpu_mxcsr_mask;		/* Valid bits in 
 u_int	cpu_clflush_line_size = 32;
 
 SYSCTL_UINT(_hw, OID_AUTO, via_feature_rng, CTLFLAG_RD,
-	&via_feature_rng, 0, "VIA C3/C7 RNG feature available in CPU");
+	&via_feature_rng, 0, "VIA RNG feature available in CPU");
 SYSCTL_UINT(_hw, OID_AUTO, via_feature_xcrypt, CTLFLAG_RD,
-	&via_feature_xcrypt, 0, "VIA C3/C7 xcrypt feature available in CPU");
+	&via_feature_xcrypt, 0, "VIA xcrypt feature available in CPU");
 
 /*
- * Initialize special VIA C3/C7 features
+ * Initialize special VIA features
  */
 static void
 init_via(void)
 {
 	u_int regs[4], val;
-	u_int64_t msreg;
 
+	/*
+	 * Check extended CPUID for PadLock features.
+	 *
+	 * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/programming_guide.pdf
+	 */
 	do_cpuid(0xc0000000, regs);
-	val = regs[0];
-	if (val >= 0xc0000001) {
+	if (regs[0] >= 0xc0000001) {
 		do_cpuid(0xc0000001, regs);
 		val = regs[3];
 	} else
-		val = 0;
+		return;
 
-	/* Enable RNG if present and disabled */
-	if (val & VIA_CPUID_HAS_RNG) {
-		if (!(val & VIA_CPUID_DO_RNG)) {
-			msreg = rdmsr(0x110B);
-			msreg |= 0x40;
-			wrmsr(0x110B, msreg);
-		}
+	/* Enable RNG if present. */
+	if ((val & VIA_CPUID_HAS_RNG) != 0) {
 		via_feature_rng = VIA_HAS_RNG;
+		wrmsr(0x110B, rdmsr(0x110B) | VIA_CPUID_DO_RNG);
 	}
-	/* Enable AES engine if present and disabled */
-	if (val & VIA_CPUID_HAS_ACE) {
-		if (!(val & VIA_CPUID_DO_ACE)) {
-			msreg = rdmsr(0x1107);
-			msreg |= (0x01 << 28);
-			wrmsr(0x1107, msreg);
-		}
+
+	/* Enable PadLock if present. */
+	if ((val & VIA_CPUID_HAS_ACE) != 0)
 		via_feature_xcrypt |= VIA_HAS_AES;
-	}
-	/* Enable ACE2 engine if present and disabled */
-	if (val & VIA_CPUID_HAS_ACE2) {
-		if (!(val & VIA_CPUID_DO_ACE2)) {
-			msreg = rdmsr(0x1107);
-			msreg |= (0x01 << 28);
-			wrmsr(0x1107, msreg);
-		}
+	if ((val & VIA_CPUID_HAS_ACE2) != 0)
 		via_feature_xcrypt |= VIA_HAS_AESCTR;
-	}
-	/* Enable SHA engine if present and disabled */
-	if (val & VIA_CPUID_HAS_PHE) {
-		if (!(val & VIA_CPUID_DO_PHE)) {
-			msreg = rdmsr(0x1107);
-			msreg |= (0x01 << 28/**/);
-			wrmsr(0x1107, msreg);
-		}
+	if ((val & VIA_CPUID_HAS_PHE) != 0)
 		via_feature_xcrypt |= VIA_HAS_SHA;
-	}
-	/* Enable MM engine if present and disabled */
-	if (val & VIA_CPUID_HAS_PMM) {
-		if (!(val & VIA_CPUID_DO_PMM)) {
-			msreg = rdmsr(0x1107);
-			msreg |= (0x01 << 28/**/);
-			wrmsr(0x1107, msreg);
-		}
+	if ((val & VIA_CPUID_HAS_PMM) != 0)
 		via_feature_xcrypt |= VIA_HAS_MM;
-	}
+	if (via_feature_xcrypt != 0)
+		wrmsr(0x1107, rdmsr(0x1107) | (1 << 28));
 }
 
 /*
@@ -159,9 +134,7 @@ initializecpu(void)
 		wrmsr(MSR_EFER, msr);
 		pg_nx = PG_NX;
 	}
-	if (cpu_vendor_id == CPU_VENDOR_CENTAUR &&
-	    CPUID_TO_FAMILY(cpu_id) == 0x6 &&
-	    CPUID_TO_MODEL(cpu_id) >= 0xf)
+	if (cpu_vendor_id == CPU_VENDOR_CENTAUR)
 		init_via();
 }
 

Modified: head/sys/i386/i386/identcpu.c
==============================================================================
--- head/sys/i386/i386/identcpu.c	Sat Mar 26 01:24:55 2011	(r220017)
+++ head/sys/i386/i386/identcpu.c	Sat Mar 26 02:02:07 2011	(r220018)
@@ -560,7 +560,8 @@ printcpuinfo(void)
 	} else if (cpu_vendor_id == CPU_VENDOR_RISE) {
 		strcpy(cpu_model, "Rise ");
 		switch (cpu_id & 0xff0) {
-		case 0x500:
+		case 0x500:	/* 6401 and 6441 (Kirin) */
+		case 0x520:	/* 6510 (Lynx) */
 			strcat(cpu_model, "mP6");
 			break;
 		default:
@@ -570,11 +571,20 @@ printcpuinfo(void)
 		switch (cpu_id & 0xff0) {
 		case 0x540:
 			strcpy(cpu_model, "IDT WinChip C6");
+			/*
+			 * http://www.centtech.com/c6_data_sheet.pdf
+			 *
+			 * I-12 RDTSC may return incoherent values in EDX:EAX
+			 * I-13 RDTSC hangs when certain event counters are used
+			 */
 			tsc_freq = 0;
 			break;
 		case 0x580:
 			strcpy(cpu_model, "IDT WinChip 2");
 			break;
+		case 0x590:
+			strcpy(cpu_model, "IDT WinChip 3");
+			break;
 		case 0x660:
 			strcpy(cpu_model, "VIA C3 Samuel");
 			break;
@@ -852,7 +862,7 @@ printcpuinfo(void)
 				);
 			}
 
-			if (cpu_vendor_id == CPU_VENDOR_CENTAUR)
+			if (via_feature_rng != 0 || via_feature_xcrypt != 0)
 				print_via_padlock_info();
 
 			if ((cpu_feature & CPUID_HTT) &&
@@ -1127,6 +1137,12 @@ finishidentcpu(void)
 			do_cpuid(0x80000008, regs);
 			cpu_procinfo2 = regs[2];
 		}
+	} else if (cpu_vendor_id == CPU_VENDOR_CENTAUR) {
+		init_exthigh();
+		if (cpu_exthigh >= 0x80000001) {
+			do_cpuid(0x80000001, regs);
+			amd_feature = regs[3] & ~(cpu_feature & 0x0183f3ff);
+		}
 	} else if (cpu_vendor_id == CPU_VENDOR_CYRIX) {
 		if (cpu == CPU_486) {
 			/*
@@ -1560,25 +1576,7 @@ print_via_padlock_info(void)
 {
 	u_int regs[4];
 
-	/* Check for supported models. */
-	switch (cpu_id & 0xff0) {
-	case 0x690:
-		if ((cpu_id & 0xf) < 3)
-			return;
-	case 0x6a0:
-	case 0x6d0:
-	case 0x6f0:
-		break;
-	default:
-		return;
-	}
-	
-	do_cpuid(0xc0000000, regs);
-	if (regs[0] >= 0xc0000001)
-		do_cpuid(0xc0000001, regs);
-	else
-		return;
-
+	do_cpuid(0xc0000001, regs);
 	printf("\n  VIA Padlock Features=0x%b", regs[3],
 	"\020"
 	"\003RNG"		/* RNG */

Modified: head/sys/i386/i386/initcpu.c
==============================================================================
--- head/sys/i386/i386/initcpu.c	Sat Mar 26 01:24:55 2011	(r220017)
+++ head/sys/i386/i386/initcpu.c	Sat Mar 26 02:02:07 2011	(r220018)
@@ -100,9 +100,9 @@ u_int	cpu_vendor_id = 0;	/* CPU vendor I
 u_int	cpu_clflush_line_size = 32;
 
 SYSCTL_UINT(_hw, OID_AUTO, via_feature_rng, CTLFLAG_RD,
-	&via_feature_rng, 0, "VIA C3/C7 RNG feature available in CPU");
+	&via_feature_rng, 0, "VIA RNG feature available in CPU");
 SYSCTL_UINT(_hw, OID_AUTO, via_feature_xcrypt, CTLFLAG_RD,
-	&via_feature_xcrypt, 0, "VIA C3/C7 xcrypt feature available in CPU");
+	&via_feature_xcrypt, 0, "VIA xcrypt feature available in CPU");
 
 #ifdef CPU_ENABLE_SSE
 u_int	cpu_fxsr;		/* SSE enabled */
@@ -420,6 +420,38 @@ init_6x86(void)
 }
 #endif /* I486_CPU */
 
+#ifdef I586_CPU
+/*
+ * IDT WinChip C6/2/2A/2B/3
+ *
+ * http://www.centtech.com/winchip_bios_writers_guide_v4_0.pdf
+ */
+static void
+init_winchip(void)
+{
+	u_int regs[4];
+	uint64_t fcr;
+
+	fcr = rdmsr(0x0107);
+
+	/*
+	 * Set ECX8, DSMC, DTLOCK/EDCTLB, EMMX, and ERETSTK and clear DPDC.
+	 */
+	fcr |= (1 << 1) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 16);
+	fcr &= ~(1ULL << 11);
+
+	/*
+	 * Additioanlly, set EBRPRED, E2MMX and EAMD3D for WinChip 2 and 3.
+	 */
+	if (CPUID_TO_MODEL(cpu_id) >= 8)
+		fcr |= (1 << 12) | (1 << 19) | (1 << 20);
+
+	wrmsr(0x0107, fcr);
+	do_cpuid(1, regs);
+	cpu_feature = regs[3];
+}
+#endif
+
 #ifdef I686_CPU
 /*
  * Cyrix 6x86MX (code-named M2)
@@ -538,71 +570,72 @@ init_mendocino(void)
 }
 
 /*
- * Initialize special VIA C3/C7 features
+ * Initialize special VIA features
  */
 static void
 init_via(void)
 {
 	u_int regs[4], val;
-	u_int64_t msreg;
+	uint64_t fcr;
+
+	/*
+	 * Explicitly enable CX8 and PGE on C3.
+	 *
+	 * http://www.via.com.tw/download/mainboards/6/13/VIA_C3_EBGA%20datasheet110.pdf
+	 */
+	if (CPUID_TO_MODEL(cpu_id) <= 9)
+		fcr = (1 << 1) | (1 << 7);
+	else
+		fcr = 0;
 
+	/*
+	 * Check extended CPUID for PadLock features.
+	 *
+	 * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/programming_guide.pdf
+	 */
 	do_cpuid(0xc0000000, regs);
-	val = regs[0];
-	if (val >= 0xc0000001) {
+	if (regs[0] >= 0xc0000001) {
 		do_cpuid(0xc0000001, regs);
 		val = regs[3];
 	} else
 		val = 0;
 
-	/* Enable RNG if present and disabled */
-	if (val & VIA_CPUID_HAS_RNG) {
-		if (!(val & VIA_CPUID_DO_RNG)) {
-			msreg = rdmsr(0x110B);
-			msreg |= 0x40;
-			wrmsr(0x110B, msreg);
-		}
+	/* Enable RNG if present. */
+	if ((val & VIA_CPUID_HAS_RNG) != 0) {
 		via_feature_rng = VIA_HAS_RNG;
+		wrmsr(0x110B, rdmsr(0x110B) | VIA_CPUID_DO_RNG);
 	}
-	/* Enable AES engine if present and disabled */
-	if (val & VIA_CPUID_HAS_ACE) {
-		if (!(val & VIA_CPUID_DO_ACE)) {
-			msreg = rdmsr(0x1107);
-			msreg |= (0x01 << 28);
-			wrmsr(0x1107, msreg);
-		}
+
+	/* Enable PadLock if present. */
+	if ((val & VIA_CPUID_HAS_ACE) != 0)
 		via_feature_xcrypt |= VIA_HAS_AES;
-	}
-	/* Enable ACE2 engine if present and disabled */
-	if (val & VIA_CPUID_HAS_ACE2) {
-		if (!(val & VIA_CPUID_DO_ACE2)) {
-			msreg = rdmsr(0x1107);
-			msreg |= (0x01 << 28);
-			wrmsr(0x1107, msreg);
-		}
+	if ((val & VIA_CPUID_HAS_ACE2) != 0)
 		via_feature_xcrypt |= VIA_HAS_AESCTR;
-	}
-	/* Enable SHA engine if present and disabled */
-	if (val & VIA_CPUID_HAS_PHE) {
-		if (!(val & VIA_CPUID_DO_PHE)) {
-			msreg = rdmsr(0x1107);
-			msreg |= (0x01 << 28/**/);
-			wrmsr(0x1107, msreg);
-		}
+	if ((val & VIA_CPUID_HAS_PHE) != 0)
 		via_feature_xcrypt |= VIA_HAS_SHA;
-	}
-	/* Enable MM engine if present and disabled */
-	if (val & VIA_CPUID_HAS_PMM) {
-		if (!(val & VIA_CPUID_DO_PMM)) {
-			msreg = rdmsr(0x1107);
-			msreg |= (0x01 << 28/**/);
-			wrmsr(0x1107, msreg);
-		}
+	if ((val & VIA_CPUID_HAS_PMM) != 0)
 		via_feature_xcrypt |= VIA_HAS_MM;
-	}
+	if (via_feature_xcrypt != 0)
+		fcr |= 1 << 28;
+
+	wrmsr(0x1107, rdmsr(0x1107) | fcr);
 }
 
 #endif /* I686_CPU */
 
+#if defined(I586_CPU) || defined(I686_CPU)
+static void
+init_transmeta(void)
+{
+	u_int regs[0];
+
+	/* Expose all hidden features. */
+	wrmsr(0x80860004, rdmsr(0x80860004) | ~0UL);
+	do_cpuid(1, regs);
+	cpu_feature = regs[3];
+}
+#endif
+
 /*
  * Initialize CR4 (Control register 4) to enable SSE instructions.
  */
@@ -644,12 +677,25 @@ initializecpu(void)
 		init_6x86();
 		break;
 #endif /* I486_CPU */
+#ifdef I586_CPU
+	case CPU_586:
+		switch (cpu_vendor_id) {
+		case CPU_VENDOR_CENTAUR:
+			init_winchip();
+			break;
+		case CPU_VENDOR_TRANSMETA:
+			init_transmeta();
+			break;
+		}
+		break;
+#endif
 #ifdef I686_CPU
 	case CPU_M2:
 		init_6x86MX();
 		break;
 	case CPU_686:
-		if (cpu_vendor_id == CPU_VENDOR_INTEL) {
+		switch (cpu_vendor_id) {
+		case CPU_VENDOR_INTEL:
 			switch (cpu_id & 0xff0) {
 			case 0x610:
 				init_ppro();
@@ -658,8 +704,9 @@ initializecpu(void)
 				init_mendocino();
 				break;
 			}
-		} else if (cpu_vendor_id == CPU_VENDOR_AMD) {
-#if defined(I686_CPU) && defined(CPU_ATHLON_SSE_HACK)
+			break;
+#ifdef CPU_ATHLON_SSE_HACK
+		case CPU_VENDOR_AMD:
 			/*
 			 * Sometimes the BIOS doesn't enable SSE instructions.
 			 * According to AMD document 20734, the mobile
@@ -676,21 +723,14 @@ initializecpu(void)
 				do_cpuid(1, regs);
 				cpu_feature = regs[3];
 			}
+			break;
 #endif
-		} else if (cpu_vendor_id == CPU_VENDOR_CENTAUR) {
-			switch (cpu_id & 0xff0) {
-			case 0x690:
-				if ((cpu_id & 0xf) < 3)
-					break;
-				/* fall through. */
-			case 0x6a0:
-			case 0x6d0:
-			case 0x6f0:
-				init_via();
-				break;
-			default:
-				break;
-			}
+		case CPU_VENDOR_CENTAUR:
+			init_via();
+			break;
+		case CPU_VENDOR_TRANSMETA:
+			init_transmeta();
+			break;
 		}
 #ifdef PAE
 		if ((amd_feature & AMDID_NX) != 0) {


More information about the svn-src-all mailing list