summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjkim <jkim@FreeBSD.org>2011-03-26 02:02:07 +0000
committerjkim <jkim@FreeBSD.org>2011-03-26 02:02:07 +0000
commitc5c94c9d77eba41e8fd67cd37c45b803e8c1fcf2 (patch)
tree52048c66c061eb964fc2755294b08defc8d45884
parent42c73e8a629b61be07778bda2b1f59905fe4f411 (diff)
downloadFreeBSD-src-c5c94c9d77eba41e8fd67cd37c45b803e8c1fcf2.zip
FreeBSD-src-c5c94c9d77eba41e8fd67cd37c45b803e8c1fcf2.tar.gz
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.
-rw-r--r--sys/amd64/amd64/identcpu.c22
-rw-r--r--sys/amd64/amd64/initcpu.c73
-rw-r--r--sys/i386/i386/identcpu.c40
-rw-r--r--sys/i386/i386/initcpu.c164
4 files changed, 146 insertions, 153 deletions
diff --git a/sys/amd64/amd64/identcpu.c b/sys/amd64/amd64/identcpu.c
index c91d507..bfb2c16 100644
--- a/sys/amd64/amd64/identcpu.c
+++ b/sys/amd64/amd64/identcpu.c
@@ -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 */
diff --git a/sys/amd64/amd64/initcpu.c b/sys/amd64/amd64/initcpu.c
index 923b28c..5a832a6 100644
--- a/sys/amd64/amd64/initcpu.c
+++ b/sys/amd64/amd64/initcpu.c
@@ -74,72 +74,47 @@ u_int cpu_mxcsr_mask; /* Valid bits in mxcsr */
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;
-
- /* 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);
- }
+ return;
+
+ /* 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();
}
diff --git a/sys/i386/i386/identcpu.c b/sys/i386/i386/identcpu.c
index e1b6476..8760562 100644
--- a/sys/i386/i386/identcpu.c
+++ b/sys/i386/i386/identcpu.c
@@ -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 */
diff --git a/sys/i386/i386/initcpu.c b/sys/i386/i386/initcpu.c
index b7fa78c..c2daf54 100644
--- a/sys/i386/i386/initcpu.c
+++ b/sys/i386/i386/initcpu.c
@@ -100,9 +100,9 @@ u_int cpu_vendor_id = 0; /* CPU vendor ID */
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) {
OpenPOWER on IntegriCloud