From owner-svn-src-all@FreeBSD.ORG Sat Mar 26 02:02:07 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 853D71065673; Sat, 26 Mar 2011 02:02:07 +0000 (UTC) (envelope-from jkim@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 745248FC0A; Sat, 26 Mar 2011 02:02:07 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p2Q227U4000182; Sat, 26 Mar 2011 02:02:07 GMT (envelope-from jkim@svn.freebsd.org) Received: (from jkim@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id p2Q227ur000177; Sat, 26 Mar 2011 02:02:07 GMT (envelope-from jkim@svn.freebsd.org) Message-Id: <201103260202.p2Q227ur000177@svn.freebsd.org> From: Jung-uk Kim Date: Sat, 26 Mar 2011 02:02:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r220018 - in head/sys: amd64/amd64 i386/i386 X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 26 Mar 2011 02:02:07 -0000 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) {