summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2014-09-04 02:25:59 +0000
committerjhb <jhb@FreeBSD.org>2014-09-04 02:25:59 +0000
commitf937116d2005d1bb59e30baff9ff73b2afd26270 (patch)
tree54e0b90111bbe41280e4bda9df0bb9bd054396fb
parent2d9d64ca44af1c88ddc687d0beab2e2d81fd765b (diff)
downloadFreeBSD-src-f937116d2005d1bb59e30baff9ff73b2afd26270.zip
FreeBSD-src-f937116d2005d1bb59e30baff9ff73b2afd26270.tar.gz
- Move blacklists of broken TSCs out of the printcpuinfo() function
and into the TSC probe routine. - Initialize cpu_exthigh once in finishidentcpu() which is called before printcpuinfo() (and matches the behavior on amd64).
-rw-r--r--sys/i386/i386/identcpu.c47
-rw-r--r--sys/x86/x86/tsc.c33
2 files changed, 44 insertions, 36 deletions
diff --git a/sys/i386/i386/identcpu.c b/sys/i386/i386/identcpu.c
index cb34bb0..9cb7fe7 100644
--- a/sys/i386/i386/identcpu.c
+++ b/sys/i386/i386/identcpu.c
@@ -65,7 +65,6 @@ __FBSDID("$FreeBSD$");
#define IDENTBLUE_CYRIXM2 2
static void identifycyrix(void);
-static void init_exthigh(void);
static u_int find_cpu_vendor_id(void);
static void print_AMD_info(void);
static void print_INTEL_info(void);
@@ -147,28 +146,6 @@ static struct {
#endif
};
-static void
-init_exthigh(void)
-{
- static int done = 0;
- u_int regs[4];
-
- if (done == 0) {
- if (cpu_high > 0 &&
- (cpu_vendor_id == CPU_VENDOR_INTEL ||
- cpu_vendor_id == CPU_VENDOR_AMD ||
- cpu_vendor_id == CPU_VENDOR_TRANSMETA ||
- cpu_vendor_id == CPU_VENDOR_CENTAUR ||
- cpu_vendor_id == CPU_VENDOR_NSC)) {
- do_cpuid(0x80000000, regs);
- if (regs[0] >= 0x80000000)
- cpu_exthigh = regs[0];
- }
-
- done = 1;
- }
-}
-
void
printcpuinfo(void)
{
@@ -180,7 +157,6 @@ printcpuinfo(void)
strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof (cpu_model));
/* Check for extended CPUID information and a processor name. */
- init_exthigh();
if (cpu_exthigh >= 0x80000004) {
brand = cpu_brand;
for (i = 0x80000002; i < 0x80000005; i++) {
@@ -354,7 +330,6 @@ printcpuinfo(void)
break;
case 0x500:
strcat(cpu_model, "K5 model 0");
- tsc_freq = 0;
break;
case 0x510:
strcat(cpu_model, "K5 model 1");
@@ -553,13 +528,6 @@ 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");
@@ -599,8 +567,6 @@ printcpuinfo(void)
case 0x540:
strcpy(cpu_model, "Geode SC1100");
cpu = CPU_GEODE1100;
- if ((cpu_id & CPUID_STEPPING) == 0)
- tsc_freq = 0;
break;
default:
strcpy(cpu_model, "Geode/NSC unknown");
@@ -1110,10 +1076,20 @@ finishidentcpu(void)
cpu_mon_max_size = regs[1] & CPUID5_MON_MAX_SIZE;
}
+ if (cpu_high > 0 &&
+ (cpu_vendor_id == CPU_VENDOR_INTEL ||
+ cpu_vendor_id == CPU_VENDOR_AMD ||
+ cpu_vendor_id == CPU_VENDOR_TRANSMETA ||
+ cpu_vendor_id == CPU_VENDOR_CENTAUR ||
+ cpu_vendor_id == CPU_VENDOR_NSC)) {
+ do_cpuid(0x80000000, regs);
+ if (regs[0] >= 0x80000000)
+ cpu_exthigh = regs[0];
+ }
+
/* Detect AMD features (PTE no-execute bit, 3dnow, 64 bit mode etc) */
if (cpu_vendor_id == CPU_VENDOR_INTEL ||
cpu_vendor_id == CPU_VENDOR_AMD) {
- init_exthigh();
if (cpu_exthigh >= 0x80000001) {
do_cpuid(0x80000001, regs);
amd_feature = regs[3] & ~(cpu_feature & 0x0183f3ff);
@@ -1128,7 +1104,6 @@ finishidentcpu(void)
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);
diff --git a/sys/x86/x86/tsc.c b/sys/x86/x86/tsc.c
index 54c4d02..31d6715 100644
--- a/sys/x86/x86/tsc.c
+++ b/sys/x86/x86/tsc.c
@@ -324,6 +324,39 @@ init_TSC(void)
if ((cpu_feature & CPUID_TSC) == 0 || tsc_disabled)
return;
+#ifdef __i386__
+ /* The TSC is known to be broken on certain CPUs. */
+ switch (cpu_vendor_id) {
+ case CPU_VENDOR_AMD:
+ switch (cpu_id & 0xFF0) {
+ case 0x500:
+ /* K5 Model 0 */
+ return;
+ }
+ break;
+ case CPU_VENDOR_CENTAUR:
+ switch (cpu_id & 0xff0) {
+ case 0x540:
+ /*
+ * 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
+ */
+ return;
+ }
+ break;
+ case CPU_VENDOR_NSC:
+ switch (cpu_id & 0xff0) {
+ case 0x540:
+ if ((cpu_id & CPUID_STEPPING) == 0)
+ return;
+ break;
+ }
+ break;
+ }
+#endif
+
probe_tsc_freq();
/*
OpenPOWER on IntegriCloud