Author: jhb Date: Thu Sep 4 02:25:59 2014 New Revision: 271082 URL: http://svnweb.freebsd.org/changeset/base/271082
Log: - 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). Modified: head/sys/i386/i386/identcpu.c head/sys/x86/x86/tsc.c Modified: head/sys/i386/i386/identcpu.c ============================================================================== --- head/sys/i386/i386/identcpu.c Thu Sep 4 02:14:57 2014 (r271081) +++ head/sys/i386/i386/identcpu.c Thu Sep 4 02:25:59 2014 (r271082) @@ -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); Modified: head/sys/x86/x86/tsc.c ============================================================================== --- head/sys/x86/x86/tsc.c Thu Sep 4 02:14:57 2014 (r271081) +++ head/sys/x86/x86/tsc.c Thu Sep 4 02:25:59 2014 (r271082) @@ -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(); /* _______________________________________________ svn-src-head@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"